IPA-114: Errors
Effective error communication is an important part of designing simple and intuitive APIs. Services returning standardized error responses enable API clients to construct centralized common error-handling logic. This common logic simplifies API client applications and eliminates the need for cumbersome custom error-handling code.
Guidance
APIs must return
ApiErrorwhen errors occur{
"error": 400,
"reason": "Bad Request",
"detail": "The request content produced validation errors.",
"errorCode": "BAD_REQUEST",
"parameters": []
}Why:The error response uses the standardized
ApiErrorformat, letting clients build common error-handling logic.APIs should avoid unexpected errors (5XX) by correctly handling validations and exposing the appropriate error user error (4XX)
{
"error": 400,
"reason": "Bad Request",
"detail": "The request content produced validation errors.",
"errorCode": "BAD_REQUEST",
"parameters": []
}Why:A malformed request surfaces as a
400 Bad Requestclient error rather than an unexpected5XXserver error.Exercise the operation with invalid and edge-case input.
Confirm validation failures and other client-caused conditions return an appropriate
4XXstatus rather than a5XX.Flag operations that return
5XXfor conditions that should have been caught and reported as client errors.
Errors must use the canonical error codes allowed for the
errorCodefield{
"error": 400,
"reason": "Bad Request",
"detail": "The request content produced validation errors.",
"errorCode": "BAD_REQUEST",
"parameters": []
}Why:The
errorCodevalueBAD_REQUESTis drawn from the canonical set of allowed error codes.APIs may make the best effort to help customers with possible next steps in case of an error by adding a
helpfieldhelpmust include a short description as descriptionhelpmust include a link to the documentation url
Methods must document any possible error and their associated HTTP status code
paths:
/groups/{groupId}/clusters/{clusterName}:
get:
operationId: getGroupCluster
responses:
"200":
description: The cluster.
"404":
description: The cluster was not found.
"401":
description: The client lacks valid credentials.Why:The operation documents each error it can return alongside its HTTP status code, so clients know what to handle.
For each operation, enumerate the errors it can return.
Confirm every possible error is documented with its associated HTTP status code in the responses.
Flag operations that can return errors that are not documented.
APIs must document
401 Unauthorizedand403 Forbiddenstatus codes for endpoints that require authentication.paths:
/groups/{groupId}/clusters/{clusterName}:
get:
operationId: getGroupCluster
responses:
"401":
description: The client lacks valid credentials.
"403":
description: The client does not have permission for the resource.Why:The authenticated endpoint documents both
401 Unauthorizedand403 Forbidden, so clients know how authentication and authorization failures are reported.- Identify endpoints that require authentication.
Confirm each documents both the
401 Unauthorizedand403 Forbiddenstatus codes.Flag authenticated endpoints missing either status code.
APIs must return
401 Unauthorizedif the client lacks valid credentials.{
"error": 401,
"reason": "Unauthorized",
"detail": "The request lacks valid authentication credentials.",
"errorCode": "UNAUTHORIZED",
"parameters": []
}Why:A request without valid credentials receives
401 Unauthorized, the status code for missing or invalid authentication.Call an authenticated endpoint with missing or invalid credentials.
Confirm the response status code is
401 Unauthorized.Flag endpoints that respond with a different status code when credentials are absent or invalid.
APIs must return
403 Forbiddenif the client is authenticated but does not have permission to access the resource.{
"error": 403,
"reason": "Forbidden",
"detail": "The client does not have permission to access this resource.",
"errorCode": "FORBIDDEN",
"parameters": []
}Why:An authenticated client without permission for the resource receives
403 Forbidden, distinguishing authorization failure from missing authentication.Call an endpoint as an authenticated client that lacks permission for the resource.
Confirm the response status code is
403 Forbidden.Flag endpoints that respond with a different status code in this case.
APIs must document the
404 Not Foundstatus code when the resource identifier includes one or more resource IDs.paths:
/groups/{groupId}/clusters/{clusterName}:
get:
operationId: getGroupCluster
responses:
"404":
description: The cluster was not found.Why:The path includes resource IDs, so the operation documents
404 Not Foundfor the case where an ID does not resolve to a resource.Identify operations whose path includes one or more resource IDs.
Confirm each documents the
404 Not Foundstatus code.- Flag such operations that omit
404 Not Found.
APIs must return a
404 Not Foundstatus code if the client provides an invalid or non-existent ID{
"error": 404,
"reason": "Not Found",
"detail": "No cluster matches the provided identifier.",
"errorCode": "NOT_FOUND",
"parameters": []
}Why:A request for an invalid or non-existent ID returns
404 Not Foundrather than a success or a400 Bad Request.Call an operation with an invalid or non-existent resource ID.
Confirm the response status code is
404 Not Found.Flag operations that respond with a different status code for invalid or non-existent IDs.
- Required fields are missing
- Data types don't match expected formats
- Values fall outside acceptable ranges
- Business rules are violated
APIs must return a
400 Bad Requeststatus code when validation fails{
"error": 400,
"reason": "Bad Request",
"detail": "The request content produced validation errors.",
"errorCode": "BAD_REQUEST",
"parameters": []
}Why:A request that fails validation returns
400 Bad Request, telling the client the request itself was invalid.Submit a request that violates the operation's validation requirements.
Confirm the response status code is
400 Bad Request.Flag operations that respond with a different status code when validation fails.
APIs must not accept invalid requests and silently modify field values to make them valid
- This violates the principle that client-owned fields must not be modified by the server (see IPA-111)
{
"error": 400,
"reason": "Bad Request",
"detail": "The request content produced validation errors.",
"errorCode": "BAD_REQUEST",
"parameters": []
}Why:The API rejects an invalid request with
400 Bad Requestinstead of silently adjusting client-owned field values to make the request valid.Submit a request with an invalid value for a client-owned field.
Confirm the request is rejected rather than accepted with the value silently modified by the server.
Flag operations that coerce or overwrite invalid client-owned field values instead of rejecting the request.
APIs should make the best effort to validate as much as possible of the request and include all validation errors in the field
badRequestDetailbadRequestDetailmust include an array of fields and each field must include:- the error description as
description - field with errors as
field
- the error description as
{
"error": 400,
"reason": "Bad Request",
"detail": "The request content produced validation errors.",
"errorCode": "BAD_REQUEST",
"parameters": [],
"badRequestDetail": {
"fields": [
{
"description": "must not be null",
"field": "groupId"
},
{
"description": "must not be empty",
"field": "authors[0].name"
}
]
}
}Why:The response collects every validation failure in
badRequestDetail.fields, each entry naming the offendingfieldand itsdescription, so the client can fix all problems at once.Submit a request that violates several validation requirements at once.
Confirm the response reports all of the violations in
badRequestDetail, with each field providing bothdescriptionandfield.Flag operations that report only the first validation error or omit the required
descriptionorfieldentries.
APIs must document the
429 Too Many Requestsstatus code for endpoints that implement rate limiting.paths:
/groups/{groupId}/clusters:
get:
operationId: listGroupClusters
responses:
"429":
description: The client has exceeded the allowed request rate.Why:The rate-limited endpoint documents
429 Too Many Requests, so clients know how exceeding the request rate is reported.Identify endpoints that implement rate limiting.
Confirm each documents the
429 Too Many Requestsstatus code.Flag rate-limited endpoints that omit
429 Too Many Requests.
APIs must return
429 Too Many Requestswhen a client exceeds the allowed request rate.{
"error": 429,
"reason": "Too Many Requests",
"detail": "The client has exceeded the allowed request rate.",
"errorCode": "TOO_MANY_REQUESTS",
"parameters": []
}Why:When a client exceeds the allowed request rate, the API returns
429 Too Many Requestsrather than continuing to serve or returning another status.Issue requests to a rate-limited endpoint until the allowed request rate is exceeded.
Confirm the response status code is
429 Too Many Requests.Flag rate-limited endpoints that respond with a different status code once the rate is exceeded.
APIs should include the
Retry-AfterHTTP response header when returning429 Too Many Requeststo indicate how long the client should wait before retrying the request.- The
Retry-Afterheader value must be expressed as time in seconds until the next request can be made.
HTTP/1.1 429 Too Many Requests
Retry-After: 30Why:The
429 Too Many Requestsresponse includesRetry-After: 30, telling the client to wait 30 seconds before retrying.Trigger a
429 Too Many Requestsresponse from a rate-limited endpoint.Confirm the response includes a
Retry-Afterheader whose value is a time in seconds.Flag
429responses that omitRetry-Afteror express it in units other than seconds.
- The
APIs should include rate limit information in response headers to help clients manage their request rates proactively:
RateLimit-Limit: The maximum number of requests allowed in the current rate limit windowRateLimit-Remaining: The number of requests remaining in the current rate limit window
HTTP/1.1 200 OK
RateLimit-Limit: 100
RateLimit-Remaining: 73Why:The response exposes
RateLimit-LimitandRateLimit-Remaining, letting the client see its budget and pace requests before hitting the limit.Call a rate-limited endpoint within the allowed rate.
Confirm the response includes the
RateLimit-LimitandRateLimit-Remainingheaders.Flag rate-limited endpoints that do not surface this rate limit information in response headers.
Authentication and Authorization
Not Found
For path parameters consider applying regex-based routing to ensure invalid IDs
are treated as 404 Not Found rather than 400 Bad Request.
Validation Errors
Validation errors occur when the client sends a request that does not meet the API's requirements. Proper validation is critical for maintaining data integrity and providing clear feedback to clients.
Validation errors typically occur when:
Rate Limiting
API Error Format
{
"error": 400, // HTTP status code (required)
"reason": "Bad Request", // Human-readable error message (optional)
"detail": "The request content produced validation errors.", // Detailed description (optional)
"errorCode": "BAD_REQUEST", // Application-specific error code (optional)
"parameters": [], // Array of additional parameters (optional)
"badRequestDetail": {
// Only present for validation errors (optional)
"fields": [
{
"field": "Request body", // Path to the problematic field
"description": "must not be null" // Description of the violation
}
]
}
}
Example
{
"badRequestDetail": {
"fields": [
{
"description": "must not be null",
"field": "groupId"
},
{
"description": "must not be empty",
"field": "authors[0].name"
}
]
},
"detail": "The request content produced validation errors.",
"error": 400,
"errorCode": "BAD_REQUEST",
"help": {
"description": "troubleshooting documentation",
"url": "https://www.mongodb.com/docs/atlas/reference/api-errors/"
},
"parameters": [],
"reason": "Bad Request"
}
New fields badRequestDetail and help are inspired by
googleapis/google/rpc/error_details.proto