Errors
All errors return a JSON body with a detail field. It holds either a plain string (errors raised by the API itself) or the underlying database error object (errors raised by the query engine).
{"detail": "Unauthorized."}{
"detail": {
"code": "PGRST100",
"message": "\"failed to parse filter (bogus.1)\"",
"details": "unexpected \"b\" expecting \"not\" or operator (eq, gt, ...)",
"hint": null
}
}HTTP status codes
| Status | Meaning | Typical cause |
|---|---|---|
200 OK | Success | - |
206 Partial Content | Partial result | A Range request that returned fewer rows than the full set |
401 Unauthorized | Missing or invalid credentials | Absent, malformed or revoked client id / secret |
404 Not Found | Endpoint does not exist | A path that is not one of the documented endpoints |
405 Method Not Allowed | Write attempted | POST, PATCH, PUT or DELETE - the API is read-only |
408 Request Timeout | Query exceeded 25s | Unbounded read, expensive count, or a wildcard text search |
429 Too Many Requests | Rate limit exceeded | Too many requests per second - the limit is shared across all users; back off and retry |
500 Internal Server Error | Query rejected or unexpected failure | Malformed filter, unknown column or table, type mismatch |
502 / 504 | Gateway error | Response too large, or an upstream timeout - reduce the page size |
Note: query errors that are logically client mistakes - a bad filter, an unknown column - currently surface as
500with the database error object indetail, rather than as400. Key your error handling on thecodefield insidedetail, not on the HTTP status alone.
Database error codes
| Code | Meaning | Fix |
|---|---|---|
PGRST100 | Filter could not be parsed | Check the operator.value form, e.g. eq.5 not =5 |
PGRST103 | Offset beyond the end of the table | Read the total from Content-Range before paging deep - see Paging past the end |
PGRST200 | No relationship between tables | Resource embedding is not supported - join client-side, see Not supported |
PGRST205 | Table not found | Check the endpoint name against the API reference |
42703 | Column does not exist | Check spelling in select, order or the filter |
42804 | Type mismatch | Usually is.true on a numeric ind_* column - use eq.1 |
Debugging checklist
GET /health- no credentials needed. If this fails, the service is down.GET /whoami- confirms your credentials are valid and shows the project they resolve to. A401here means a credentials problem, not a query problem.- Add
limit=1- if a failing query then succeeds, it was a timeout, not a syntax error. - Strip the query back to
?limit=1and add filters one at a time to find the one at fault. - Read the
hintanddetailsfields in the error body; PostgREST often names the exact column or suggests the intended table.
Updated about 2 hours ago
Did this page help you?