diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index 6015b6d48..fc7f2edb6 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -57,3 +57,11 @@ div.line-block { margin-right: auto; margin-bottom: 24px; } + +.wy-table-responsive table td { + white-space: normal !important; +} + +.wy-table-responsive { + overflow: visible !important; +} diff --git a/docs/admin.rst b/docs/admin.rst index acdfc29a1..e7a7448f9 100644 --- a/docs/admin.rst +++ b/docs/admin.rst @@ -153,6 +153,11 @@ Server Version When debugging a problem it's important to verify the PostgREST version. At any time you can make a request to the running server and determine exactly which version is deployed. Look for the :code:`Server` HTTP response header, which contains the version number. +Errors +------ + +See the :doc:`Errors ` reference page for detailed information on the errors that PostgREST returns. + .. _pgrst_logging: Logging diff --git a/docs/api.rst b/docs/api.rst index ab4f997fb..7acaafa36 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -539,6 +539,8 @@ Here ``Quote:"`` and ``Backslash:\`` are percent-encoded values. Note that ``%5C Some HTTP libraries might encode URLs automatically(e.g. :code:`axios`). In these cases you should use double quotes :code:`""` directly instead of :code:`%22`. +.. _ordering: + Ordering -------- @@ -827,7 +829,9 @@ When a singular response is requested but no entries are found, the server respo { "message": "JSON object requested, multiple (or no) rows returned", - "details": "Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row" + "details": "Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row", + "hint": null, + "code": "PGRST505" } .. note:: @@ -1714,6 +1718,8 @@ By specifying the ``on_conflict`` query parameter, you can make UPSERT work on a ] EOF +.. _upsert_put: + PUT ~~~ @@ -2636,8 +2642,10 @@ You can set the ``response.status`` GUC to override the default status code Post HTTP/1.1 418 I'm a teapot - {"message" : "The requested entity body is short and stout.", - "hint" : "Tip it over and pour it out."} + { + "message" : "The requested entity body is short and stout.", + "hint" : "Tip it over and pour it out." + } If the status code is standard, PostgREST will complete the status message(**I'm a teapot** in this example). @@ -2693,72 +2701,9 @@ Returns: HTTP/1.1 402 Payment Required Content-Type: application/json; charset=utf-8 - {"hint":"Upgrade your plan","details":"Quota exceeded"} - -.. _status_codes: - -HTTP Status Codes ------------------ - -PostgREST translates `PostgreSQL error codes `_ into HTTP status as follows: - -+--------------------------+-------------------------+---------------------------------+ -| PostgreSQL error code(s) | HTTP status | Error description | -+==========================+=========================+=================================+ -| 08* | 503 | pg connection err | -+--------------------------+-------------------------+---------------------------------+ -| 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 | -+--------------------------+-------------------------+---------------------------------+ -| 53* | 503 | insufficient resources | -+--------------------------+-------------------------+---------------------------------+ -| 54* | 413 | 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 | -+--------------------------+-------------------------+---------------------------------+ -| 42501 | | if authenticated 403, | insufficient privileges | -| | | else 401 | | -+--------------------------+-------------------------+---------------------------------+ -| other | 400 | | -+--------------------------+-------------------------+---------------------------------+ + { + "message": "Payment Required", + "details": "Quota exceeded", + "hint": "Upgrade your plan", + "code": "PT402" + } diff --git a/docs/errors.rst b/docs/errors.rst new file mode 100644 index 000000000..39fa807a4 --- /dev/null +++ b/docs/errors.rst @@ -0,0 +1,301 @@ +.. _error_source: + +Error Source +============ + +For the most part, error messages will come directly from the database with the same `format that PostgreSQL uses `_, in other words, PostgREST will convert the ``MESSAGE``, ``DETAIL``, ``HINT`` and ``ERRCODE`` from the PostgreSQL error to JSON format and add an HTTP status code to the response (see :ref:`status_codes`). For instance, this is the error you will get when querying a nonexistent table: + +.. code-block:: http + + GET /nonexistent_table?id=eq.1 HTTP/1.1 + +.. code-block:: json + + { + "hint": null, + "details": null, + "code": "42P01", + "message": "relation \"api.nonexistent_table\" does not exist" + } + +However, some errors do come from PostgREST itself (such as those related to the :ref:`schema_cache`). These have the same structure as the PostgreSQL errors (message, details, hint and code) but are differentiated by the ``PGRST`` prefix in the ``code`` field (see :ref:`pgrst_errors`). For instance, when querying a function that does not exist, the error will be: + +.. code-block:: http + + POST /rpc/nonexistent_function HTTP/1.1 + +.. code-block:: json + + { + "hint": "If a new function was created in the database with this name and parameters, try reloading the schema cache.", + "details": null + "code": "PGRST202", + "message": "Could not find the api.nonexistent_function() function in the schema cache" + } + +.. _status_codes: + +HTTP Status Codes +================= + +PostgREST translates `PostgreSQL error codes `_ into HTTP status as follows: + ++--------------------------+-------------------------+---------------------------------+ +| PostgreSQL error code(s) | HTTP status | Error description | ++==========================+=========================+=================================+ +| 08* | 503 | pg connection err | ++--------------------------+-------------------------+---------------------------------+ +| 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 | ++--------------------------+-------------------------+---------------------------------+ +| 53* | 503 | insufficient resources | ++--------------------------+-------------------------+---------------------------------+ +| 54* | 413 | 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 | ++--------------------------+-------------------------+---------------------------------+ +| 42501 | | if authenticated 403, | insufficient privileges | +| | | else 401 | | ++--------------------------+-------------------------+---------------------------------+ +| other | 400 | | ++--------------------------+-------------------------+---------------------------------+ + +.. _pgrst_errors: + +PostgREST Error Codes +===================== + +PostgREST error codes have the form ``PGRSTgxx``, where ``PGRST`` is the prefix that differentiates the error from a PostgreSQL error, ``g`` is the group where the error belongs and ``xx`` is the number that identifies the error in the group. + +.. _pgrst0**: + +Group 0 - Connection +-------------------- + +Related to the connection with the database. + ++---------------+-------------------------------------------------------------+ +| Code | Description | ++===============+=============================================================+ +| .. _pgrst000: | Could not connect with the database due to an incorrect | +| | :ref:`db-uri` or due to the PostgreSQL service not running. | +| PGRST000 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst001: | Could not connect with the database due to an internal | +| | error. | +| PGRST001 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst002: | Could not connect with the database when building the | +| | :ref:`schema_cache` due to the PostgreSQL service not | +| PGRST002 | running. | ++---------------+-------------------------------------------------------------+ + +.. _pgrst1**: + +Group 1 - Api Request +--------------------- + +Related to the HTTP request elements. + ++---------------+-------------------------------------------------------------+ +| Code | Description | ++===============+=============================================================+ +| .. _pgrst100: | Parsing error in the query string parameter. | +| | See :ref:`h_filter`, :ref:`operators` and :ref:`ordering`. | +| PGRST100 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst101: | For :ref:`functions `, only ``GET`` and ``POST`` | +| | verbs are allowed. Any other verb will throw this error. | +| PGRST101 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst102: | Related to the request body structure. | +| | See :ref:`insert_update`. | +| PGRST102 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst103: | Related to :ref:`limits`. | +| | | +| PGRST103 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst104: | Either the :ref:`filter operator ` is missing | +| | or it doesn't exist. | +| PGRST104 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst105: | Related to an :ref:`UPSERT using PUT `. | +| | | +| PGRST105 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst106: | The schema specified when | +| | :ref:`switching schemas ` is not present | +| PGRST106 | in the :ref:`db-schemas` configuration variable. | ++---------------+-------------------------------------------------------------+ +| .. _pgrst107: | The ``Content-Type`` sent in the request is invalid. | +| | | +| PGRST107 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst108: | The filter is applied to a embedded resource that is not | +| | specified in the ``select`` part of the query string. | +| PGRST108 | See :ref:`embed_filters`. | ++---------------+-------------------------------------------------------------+ + +.. _pgrst2**: + +Group 2 - Schema Cache +---------------------- + +Related to a :ref:`stale schema cache `. Most of the time, these errors are solved by :ref:`reloading the schema cache `. + ++---------------+-------------------------------------------------------------+ +| Code | Description | ++===============+=============================================================+ +| .. _pgrst200: | Caused by :ref:`stale_fk_relationships`, otherwise any of | +| | the embedding resources or the relationship itself may not | +| PGRST200 | exist in the database. | ++---------------+-------------------------------------------------------------+ +| .. _pgrst201: | Related to :ref:`embed_disamb`. | +| | | +| PGRST201 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst202: | Caused by a :ref:`stale_function_signature`, otherwise | +| | the function may not exist in the database. | +| PGRST202 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst203: | Caused by requesting overloaded functions with the same | +| | argument names but different types, or by using a ``POST`` | +| PGRST203 | 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. | ++---------------+-------------------------------------------------------------+ + +.. _pgrst3**: + +Group 3 - JWT errors +-------------------- + +Related to the authentication process using JWT. You can follow the :ref:`tut1` for an example on how to implement authentication and the :doc:`Authentication page ` for more information on this process. + ++---------------+-------------------------------------------------------------+ +| Code | Description | ++===============+=============================================================+ +| .. _pgrst300: | A :ref:`JWT secret ` is missing from the | +| | configuration. | +| PGRST300 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst301: | Any error related to the verification of the JWT, | +| | which means that the JWT provided is invalid in some way. | +| PGRST301 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst302: | Attempted to do a request without | +| | :ref:`authentication ` when the anonymous role | +| PGRST302 | is disabled by not setting it in :ref:`db-anon-role`. | ++---------------+-------------------------------------------------------------+ + +.. _pgrst4**: + +Group 4 - Hasql +--------------- + +Related to `the library `_ that PostgREST uses to connect to the database. If you encounter any of these errors, you may have stumbled on a PostgREST bug, please `open an issue `_ and we'll be glad to fix it. + ++---------------+-------------------------------------------------------------+ +| Code | Description | ++===============+=============================================================+ +| .. _pgrst400: | Internal error: Unexpected Result. | +| | | +| PGRST400 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst401: | Internal error: Attempted to parse more columns than | +| | there are in the result. | +| PGRST401 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst402: | Internal error: Attempted to parse a NULL as some value. | +| | | +| PGRST402 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst403: | Internal error: Wrong value parser used. | +| | | +| PGRST403 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst404: | Internal error: Unexpected amount of rows. | +| | | +| PGRST404 | | ++---------------+-------------------------------------------------------------+ + +.. _pgrst5**: + +Group 5 - General +----------------- + +These are uncategorized errors. + ++---------------+-------------------------------------------------------------+ +| Code | Description | ++===============+=============================================================+ +| .. _pgrst500: | Related to :ref:`guc_resp_hdrs`. | +| | | +| PGRST500 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst501: | The status code must be a positive integer. | +| | See :ref:`guc_resp_status`. | +| PGRST501 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst502: | Related to :ref:`binary_output`. See :ref:`providing_img` | +| | for an example on requesting images. | +| PGRST502 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst503: | For an :ref:`UPSERT using PUT `, when | +| | :ref:`limits and offsets ` are used. | +| PGRST503 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst504: | For an :ref:`UPSERT using PUT `, when the | +| | primary key in the query string and the body are different. | +| PGRST504 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst505: | More than 1 or no items where returned when requesting | +| | a singular response. See :ref:`singular_plural`. | +| PGRST505 | | ++---------------+-------------------------------------------------------------+ +| .. _pgrst506: | The HTTP verb used in the request in not supported. | +| | | +| PGRST506 | | ++---------------+-------------------------------------------------------------+ diff --git a/docs/index.rst b/docs/index.rst index 8fa7b04f7..ea08aa3ad 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -145,9 +145,16 @@ Technical references for PostgREST's functionality. schema_cache.rst +.. toctree:: + :caption: Errors + :hidden: + + errors.rst + - :doc:`API ` - :doc:`configuration` - :doc:`Schema Cache ` +- :doc:`Errors ` Topic guides ------------ diff --git a/docs/schema_cache.rst b/docs/schema_cache.rst index 11d0f9510..4b59c7988 100644 --- a/docs/schema_cache.rst +++ b/docs/schema_cache.rst @@ -27,6 +27,8 @@ in order to avoid repeating this work, PostgREST uses a schema cache. | | Function signature | +--------------------------------------------+-------------------------------------------------------------------------------+ +.. _stale_schema: + The Stale Schema Cache ---------------------- @@ -56,8 +58,10 @@ The result will be an error: .. code-block:: json { - "hint": "If a new foreign key between these entities was created in the database, try reloading the schema cache.", - "message": "Could not find a relationship between cities and countries in the schema cache" + "hint": "Verify that 'cities' and 'countries' exist in the schema 'api' and that there is a foreign key relationship between them. If a new relationship was created, try reloading the schema cache.", + "details": null, + "code": "PGRST200", + "message": "Could not find a relationship between 'cities' and 'countries' in the schema cache" } As you can see, PostgREST couldn't find the newly created foreign key in the schema cache. See :ref:`schema_reloading` and :ref:`auto_schema_reloading` to solve this issue. @@ -89,7 +93,9 @@ The same issue will occur on newly created functions on a running PostgREST. .. code-block:: json { - "hint": "If a new function was created in the database with this name and arguments, try reloading the schema cache.", + "hint": "If a new function was created in the database with this name and parameters, try reloading the schema cache.", + "details": null, + "code": "PGRST202", "message": "Could not find the api.plus_one(num) function in the schema cache" } diff --git a/docs/tutorials/tut0.rst b/docs/tutorials/tut0.rst index a0ffb936c..5a2ed1604 100644 --- a/docs/tutorials/tut0.rst +++ b/docs/tutorials/tut0.rst @@ -223,7 +223,7 @@ Response is 401 Unauthorized: "hint": null, "details": null, "code": "42501", - "message": "permission denied for relation todos" + "message": "permission denied for table todos" } There we have it, a basic API on top of the database! In the next tutorials we will see how to extend the example with more sophisticated user access controls, and more tables and queries. diff --git a/docs/tutorials/tut1.rst b/docs/tutorials/tut1.rst index cb307dc4b..33ef764e7 100644 --- a/docs/tutorials/tut1.rst +++ b/docs/tutorials/tut1.rst @@ -175,7 +175,12 @@ After expiration, the API returns HTTP 401 Unauthorized: .. code-block:: json - {"message":"JWT expired"} + { + "hint": null, + "details": null, + "code": "PGRST301", + "message": "JWT expired" + } Bonus Topic: Immediate Revocation --------------------------------- diff --git a/postgrest.dict b/postgrest.dict index 1ac2dd976..2b15bd67b 100644 --- a/postgrest.dict +++ b/postgrest.dict @@ -49,6 +49,7 @@ GUC gucs Gumbs Haskell +Hasql Heroku HMAC Homebrew @@ -170,6 +171,7 @@ Tyll TypeScript UI ui +uncategorized unicode unix updatable