Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add error codes (supabase#1377)
Adds proper error codes with API versioning. From now on, all responses that end in a 4XX HTTP status code will include a textual description of the error that occurred. Error responses on API versions before `2024-01-01` have this schema: ```json { "code": "<http status code>", "msg": "<descriptive error message>", "error_code": "<textual error code>" } ``` Error responses on API version on or after `2024-01-01` have this schema: ```json { "code": "<textual error code>", "message": "<descriptive error message>" } ``` API versions are controlled by submitting an `X-Supabase-Api-Version` header to the request. A missing or invalid value assumes the "initial" API version as used before the introduction of API version `2024-01-01`. Error code contract for API version `2024-01-01`: 1. Error codes will not be renamed. You can safely rely on them. 2. HTTP status codes are _mostly_ fixed, but you should not rely on them except the class 4XX vs 5XX. 3. Error messages are a _developer aid._ They may change across deployed version. You should not rely on them, but if you want you can show them to your users. Error translations should be based on the error code! Of the 4XX HTTP status code class, only these codes are allowed to be used in API version `2024-01-01` according to these rules. The purpose of this is to keep proper HTTP semantics. The tuple `(http_status_code, error_code)` shouldn't be used by clients! <table> <thead class="simple-table-header"><tr id="865bd663-796b-4bdc-a53d-8aecbdc35ab5"><th id="=Aef" class="simple-table-header-color simple-table-header" style="width:142.9666748046875px">HTTP Status Code</th><th id="UuUa" class="simple-table-header-color simple-table-header" style="width:390px">When to use?</th><th>Primary Fault At</th></tr></thead><tbody><tr id="794cf424-14a8-449c-880f-b6073206e70b"><td id="=Aef" class="" style="width:142.9666748046875px">400 Bad Request</td><td id="UuUa" class="" style="width:390px">Inputs (body, headers) and their contents are not valid as a whole, or parts of them. Example: bad JSON, bad JSON object, using two mutually exclusive JSON fields, missing required fields, wrong encoding…<br><br>If the answer to this question is <br><em>yes</em> then you should probably use 400: Is there some <em>technical</em> thing the developer should do to get a different status code?</td><td>Developer.<br><br>MUST NEVER OCCUR WHEN USING AN OFFICIAL SUPABASE LIBRARY.<br><br>Why?<br>- Library should not send invalid requests.<br>- If occurring, means: improper types, no client-side validation.<br></td></tr><tr id="11fb5eb7-0d25-41f3-998b-86162dedcf93"><td id="=Aef" class="" style="width:142.9666748046875px">401 Unauthorized</td><td id="UuUa" class="" style="width:390px">You must use this code if security headers or inputs are missing, and are not valid to some extent. Example: missing JWT, missing CAPTCHA token, missing important query params that serve to authenticate the caller.<br><br>You may use 400 instead if the security headers or inputs are provided and relatively valid (valid JWT signature, bad claims) instead, though prefer 401 over 400 unless it aids in DX.<br><br>Do not use this code to signal that the user does not have sufficient application privileges.<br><br>If the answer to this question is <br><em>yes</em> then you should use 401: Are the credentials the user/client sending missing or invalid in form, structure, encoding? </td><td>Developer.<br><br>MUST NEVER OCCUR WHEN USING AN OFFICIAL SUPABASE LIBRARY. <br><br>Why?<br>- Library should never send improper requests (missing authorization headers for features that require authorization).<br>- If occurring means: broken logic, improper types, no client-side validation.<br></td></tr><tr id="fa0e33d5-425c-442d-bdfb-18d68e11cc9e"><td id="=Aef" class="" style="width:142.9666748046875px">403 Forbidden</td><td id="UuUa" class="" style="width:390px">Do not use this code for bad JWT format, missing headers or other validation on security sensitive payloads. Return 400 on those.<br><br>Once security payloads have been validated in structure, only return this error if the user/client can be authenticated properly but they do not possess the proper authorization to access the resource.<br><br>If the answer to this question is <br><em>yes</em> then you should use 403: Should the user/client be someone else to get a different status code?<br><br>In some cases you should prefer 200 responses with empty bodies, akin to RLS behavior.<br></td><td>User.<br><br>Developer is at fault for not hiding the feature sufficiently.<br><br>Can rarely occur when using Supabase libraries, and in such cases it means docs / explanation problems.<br></td></tr><tr id="c16ac87c-7433-4750-bdf8-a8a47148b5da"><td id="=Aef" class="" style="width:142.9666748046875px">404 Not Found</td><td id="UuUa" class="" style="width:390px">Do not use this for missing objects in the database. Prefer using 422 instead.<br><br>Use only if the URL cannot be fully validated, resulting in a resource that cannot be properly identified. If there’s no variables in the path, this code must not be used.<br><br>Good:<br>- /users/<not-uuid><br>- /users/<uuid> (but such a user does not exist)<br><br>Bad:<br>- /token?grant_type=password (no variables in URL)<br>- /sessions (no variables in URL)<br><br>For cases where a feature is disabled on a server consider using 501 or 422.<br><br>For requests that “look up” entities consider using 200 with an empty/null response body or 204 No Content instead.<br></td><td>Developer.<br><br>MUST NEVER OCCUR WHEN USING AN OFFICIAL SUPABASE LIBRARY. <br><br>Why?<br>- Library should never send improperly formatted URLs, or encode data in URLs that it knows to be invalid.<br>- Ideally library should not take in freeform input about entities, and should use some “proof” that the entity exists. Example: calling methods on objects returned by a list/find-by-id method.<br>- In some situations it’s inevitable (like in admin APIs).<br></td></tr><tr id="ab865315-a594-4490-ab71-254cd536c461"><td id="=Aef" class="" style="width:142.9666748046875px"><a href="https://www.rfc-editor.org/rfc/rfc9110#section-15.5.21">422 Unprocessable Entity</a></td><td id="UuUa" class="" style="width:390px">Do not use for bad inputs!<br><br>Once all inputs to a request have been validated to the fullest extent possible (e.g. OK to validate an email address format, but not necessary to validate that there’s a SMTP server listening), use this status code to signal errors with the processing logic. This includes all logic dependent on database state (user exists, or doesn’t). All third-party expected errors (like calling into a third service) should end with 422.<br><br>If the answer to this question is <br><em>yes</em> then you should use 422: Is there something different that the user should do to get a different status code?</td><td>User.<br><br>Developer is at fault for using the feature in an improper part of the flow.<br><br>Can rarely occur when using Supabase libraries, and in such cases it means docs / explanation problems.<br></td></tr><tr id="58d30ecb-ca21-4bcf-ab4f-79e352eea516"><td id="=Aef" class="" style="width:142.9666748046875px">429 Too Many Requests</td><td id="UuUa" class="" style="width:390px">Only use this for rate-limiting or other cases that limit the number of requests. Third-party rate-limits should be propagated with this error.</td><td>User.<br><br>Developer should have implemented a better UX to prevent reaching this error for legitimate users. (Disabling buttons, adding timeout UI elements…)<br></td></tr><tr id="305e93a6-65e9-4670-a778-523470696d4a"><td id="=Aef" class="" style="width:142.9666748046875px">500 Internal Server Error</td><td id="UuUa" class="" style="width:390px">Use this for any <em>unexpected</em> errors when processing a request. Default to this code if you can’t find a 4XX error code for it.</td><td>Supabase. Developer in some cases (such as when changing database contents).<br><br>The cause of this error should not be situations arising from official Supabase libraries (such as sending inputs that crash the server).<br><br></td></tr><tr id="3fdd4130-137b-49d4-807e-003ce7baf4af"><td id="=Aef" class="" style="width:142.9666748046875px">501 Not Implemented</td><td id="UuUa" class="" style="width:390px">A feature is disabled, not configured (properly), blocked or otherwise unavailable.</td><td>Developer, for not enabling or configuring features properly.</td></tr></tbody> </table> --------- Co-authored-by: joel <[email protected]>
- Loading branch information