Error Codes
Identify PostgREST errors and resolve them
The docs reflect the error codes and information in PostgREST's official docs.
PostgREST error codes#
Error codes from the Data API are returned as JSON objects
1{2 "code": "42703",3 "details": null,4 "hint": "Perhaps you meant to reference the column some_table.fake_col",5 "message": "column some_table.fake_col does not exist"6}Here is the full list of error codes and their descriptions:
Database level errors#
To understand the errors reference the Postgres Error Docs.
Here's the text formatted as a proper markdown table:
| Postgres error code(s) | HTTP status | Error description |
|---|---|---|
| 08* | 503 | connection error |
| 09* | 500 | triggered action exception |
| 0L* | 403 | invalid grantor |
| 0P* | 403 | invalid role specification |
| 23503 | 409 | foreign key violation |
| 23505 | 409 | uniqueness violation |
| 25006 | 405 | read only SQL transaction |
| 25* | 500 | invalid transaction state |
| 28* | 403 | invalid auth specification |
| 2D* | 500 | invalid transaction termination |
| 38* | 500 | external routine exception |
| 39* | 500 | external routine invocation |
| 3B* | 500 | savepoint exception |
| 40* | 500 | transaction rollback |
| 53400 | 500 | config limit exceeded |
| 53* | 503 | insufficient resources |
| 54* | 500 | too complex |
| 55* | 500 | obj not in prerequisite state |
| 57* | 500 | operator intervention |
| 58* | 500 | system error |
| F0* | 500 | config file error |
| HV* | 500 | foreign data wrapper error |
| P0001 | 400 | default code for "raise" |
| P0* | 500 | PL/pgSQL error |
| XX* | 500 | internal error |
| 42883 | 404 | undefined function |
| 42P01 | 404 | undefined table |
| 42P17 | 500 | infinite recursion |
| 42501 | if authenticated 403, else 401 | insufficient privileges |
| other | 400 |
API level errors#
Connection errors#
Errors that prevent that data API from interacting with Postgres.
| Code | HTTP status | Description |
|---|---|---|
| PGRST000 | 503 | Could not connect with the database due to an incorrect connection string or due to the Postgres service not running. |
| PGRST001 | 503 | Could not connect with the database due to an internal error. |
| PGRST002 | 503 | Could not connect with the database when building the schema cache |
| PGRST003 | 504 | The request timed out waiting for a connection from PostgREST's internal pool |
API requests#
Errors with data structures or request formatting
| Code | HTTP status | Description |
|---|---|---|
| PGRST100 | 400 | Parsing error in the query string parameter. |
| PGRST101 | 405 | For database functions, only GET and POST verbs are allowed. Any other verb will throw this error. |
| PGRST102 | 400 | An invalid request body was sent(e.g. an empty body or malformed JSON). |
| PGRST103 | 416 | An invalid range was specified for limits. |
| PGRST105 | 405 | An invalid UPDATE/UPSERT request was done |
| PGRST106 | 406 | The schema specified when switching schemas is not exposed to the API. |
| PGRST107 | 415 | The Content-Type sent in the request is invalid. |
| PGRST108 | 400 | The filter is applied to an embedded resource that is not specified in the select part of the query string. |
| PGRST111 | 500 | An invalid response.headers was set. |
| PGRST112 | 500 | The status code must be a positive integer. |
| PGRST114 | 400 | For an UPSERT using PUT when limits and offsets are used. |
| PGRST115 | 400 | For an UPSERT using PUT when the primary key in the query string and the body are different. |
| PGRST116 | 406 | More than 1 or no items where returned when requesting a singular response. |
| PGRST117 | 405 | The HTTP verb used in the request in not supported. |
| PGRST118 | 400 | Could not order the result using the related table because there is no many-to-one or one-to-one relationship between them. |
| PGRST120 | 400 | An embedded resource can only be filtered using the is.null or not.is.null operators. |
| PGRST121 | 500 | API can't parse the JSON objects in RAISE PGRST error. |
| PGRST122 | 400 | Invalid preferences found in Prefer header with Prefer: handling=strict. |
| PGRST123 | 400 | Aggregate functions are disabled. |
| PGRST124 | 400 | max-affected preference is violated. |
| PGRST125 | 404 | Invalid path is specified in request URL. |
| PGRST126 | 404 | Open API config is disabled but API root path is accessed. |
| PGRST127 | 400 | The feature specified in the details field is not implemented. |
| PGRST128 | 400 | max-affected preference is violated with RPC call. |
Schema cache errors#
The API is unable to identify relationships or objects within the query requests.
| Code | HTTP status | Description |
|---|---|---|
| PGRST200 | 400 | Caused by stale foreign key relationships, otherwise any of the embedding resources or the relationship itself may not exist in the database. |
| PGRST201 | 300 | An ambiguous embedding request was made. |
| PGRST202 | 404 | Caused by a stale function signature, otherwise the function may not exist in the database. |
| PGRST203 | 300 | Caused by requesting overloaded functions with the same argument names but different types, or by using a POST verb to request overloaded functions with a JSON or JSONB type unnamed parameter. The solution is to rename the function or add/modify the names of the arguments. |
| PGRST204 | 400 | Caused when the column specified in the columns query parameter is not found. |
| PGRST205 | 404 | Caused when the table specified in the URI is not found. |
Authentication errors#
The request lacks the proper credentials to request data
| Code | HTTP status | Description |
|---|---|---|
| PGRST300 | 500 | PostgREST does not have an active JWT secret to validate requests |
| PGRST301 | 401 | Provided JWT couldn't be decoded or it is invalid. |
| PGRST302 | 401 | Attempted to do a request without the header Auth: Bearer when the anonymous role is disabled. |
| PGRST303 | 401 | JWT claims validation or parsing failed. |
Internal errors#
Data API error unspecified
| Code | HTTP status | Description |
|---|---|---|
| PGRSTX00 | 500 | Internal errors related to the library used for connecting to the database. |
Viewing errors in the logs#
One can filter for API errors in the log explorer. Below are useful queries for filtering and analyzing API errors:
Find all API errors that occurred at the database level#
1select2 cast(postgres_logs.timestamp as datetime) as timestamp,3 event_message,4 parsed.error_severity,5 parsed.user_name,6 parsed.query,7 parsed.detail,8 parsed.hint,9 parsed.sql_state_code,10 parsed.backend_type11from12 postgres_logs13 cross join unnest(metadata) as metadata14 cross join unnest(metadata.parsed) as parsed15where16 regexp_contains(parsed.error_severity, 'ERROR|FATAL|PANIC')17 and parsed.user_name = 'authenticator' -- the authenticator role represents the database API18order by timestamp desc19limit 100;Find specific database error from the data API#
1select2 cast(postgres_logs.timestamp as datetime) as timestamp,3 event_message,4 parsed.error_severity,5 parsed.user_name,6 parsed.query,7 parsed.detail,8 parsed.hint,9 parsed.sql_state_code,10 parsed.backend_type11from12 postgres_logs13 cross join unnest(metadata) as metadata14 cross join unnest(metadata.parsed) as parsed15where parsed.sql_state_code like '42501' and parsed.user_name = 'authenticator' -- the authenticator role represents the database API16order by timestamp desc17limit 100;PostgREST error codes are only captured in the logs for projects running V14+. You can check your PostgREST version and upgrade your project in the Infrastructure Settings
Find specific API error#
1select2 cast(timestamp as datetime) as timestamp,3 status_code,4 event_message,5 coalesce(proxy_status, 'not_recorded') as error_codes,6 path7from8 edge_logs9 cross join unnest(metadata) as metadata10 cross join unnest(response) as response11 cross join unnest(request) as request12where13 status_code >= 30014 and regexp_contains(path, '^/rest/v1/')15 and regexp_contains(proxy_status, '(?i)THE_RELEVANT_STATUS_CODE');Count errors per path by hour:#
1select2 format_timestamp(3 "%c",4 timestamp_trunc(cast(edge_logs.timestamp as timestamp), hour),5 "UTC"6 ) as hour,7 count(proxy_status) as error_count,8 path,9 coalesce(proxy_status, 'not_recorded') as error_codes10from11 edge_logs12 cross join unnest(metadata) as metadata13 cross join unnest(response) as response14 cross join unnest(response.headers) as headers15 cross join unnest(request) as request16where status_code >= 300 and regexp_contains(path, '^/rest/v1/')17group by hour, proxy_status, path;Find data API request from specific authenticated user#
1select2 cast(timestamp as datetime) as timestamp,3 event_message,4 cf_connecting_ip as requesters_ip,5 url as request_url,6 request.method as request_method,7 sb.auth_user as user_id,8 apikey_payload.role as apikey_role,9 authorization_payload.role as authorization_token_role,10 user_agent,11 city,12 country,13 continent,14 postalCode15from16 edge_logs17 cross join unnest(metadata) as metadata18 cross join unnest(request) as request19 cross join unnest(sb) as sb20 cross join unnest(jwt) as jwt21 cross join unnest(jwt.apikey) as jwt_apikey22 cross join unnest(jwt_apikey.payload) as apikey_payload23 cross join unnest(authorization) as authorization_key24 cross join unnest(authorization_key.payload) as authorization_payload25 cross join unnest(headers) as headers26 cross join unnest(cf) as cf27 cross join unnest(response) as response28where regexp_contains(path, '^/rest/v1/') and sb.auth_user = 'SOME_USER_ID' -- <---ADD USER_ID from auth.users table29order by timestamp desc;