Skip to content

Rate limiter returns HTTP 500 instead of 429 when limit exceeded #120

@mgoldsborough

Description

@mgoldsborough

Summary

When a client exceeds the rate limit on the public registry API, @fastify/rate-limit surfaces as an HTTP 500 (INTERNAL_ERROR, isOperational: false) instead of a proper 429 Too Many Requests. Clients can't distinguish throttling from a real server fault, and it pollutes error monitoring with non-actionable 500s.

Evidence

Observed against staging during a burst of SDK integration requests (make smoke). Single requests succeed (200); rapid bursts from one IP trip the limiter and return 500:

url: /v1/bundles/@nimblebraininc/echo/versions
statusCode: 500
errorCode: INTERNAL_ERROR
isOperational: false
stack: Error: Rate limit exceeded, retry in 39 seconds
    at Object.defaultErrorResponse [as errorResponseBuilder]
       (@fastify/rate-limit/index.js:32:15)

The rate-limit plugin throws an Error that the global error handler classifies as non-operational → 500.

Expected

  • Status 429 with Retry-After header
  • A RATE_LIMITED / operational error code (not INTERNAL_ERROR)
  • Not logged as a level-50 internal error

Likely fix

Configure @fastify/rate-limit's errorResponseBuilder to return a 429 payload (and/or map it in the global error handler), so it's treated as operational.

Notes

Pre-existing; surfaced during the #119 deploy smoke run. The 500s there were this limiter behavior, not a regression. Low severity (functionality works) but worth fixing for client ergonomics and clean monitoring.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions