Skip to content

Error Handling

Error handling configuration for mapping PostgreSQL errors to HTTP responses.

Overview

json
{
  "ErrorHandlingOptions": {
    "RemoveTypeUrl": false,
    "RemoveTraceId": true,
    "DefaultErrorCodePolicy": "Default",
    "TimeoutErrorMapping": {
      "StatusCode": 504,
      "Title": "Command execution timed out",
      "Details": null,
      "Type": null
    },
    "ErrorCodePolicies": [
      {
        "Name": "Default",
        "ErrorCodes": {
          "42501": {"StatusCode": 403, "Title": "Insufficient Privilege", "Details": null, "Type": null},
          "57014": {"StatusCode": 205, "Title": "Cancelled", "Details": null, "Type": null},
          "P0001": {"StatusCode": 400, "Title": null, "Details": null, "Type": null},
          "P0004": {"StatusCode": 400, "Title": null, "Details": null, "Type": null}
        }
      }
    ]
  }
}

Settings Reference

SettingTypeDefaultDescription
RemoveTypeUrlboolfalseRemove Type URL from error responses. Default Type URL points to RFC documentation based on HTTP status code.
RemoveTraceIdbooltrueRemove TraceId field from error responses. TraceId is useful for correlating logs with errors.
DefaultErrorCodePolicystring"Default"Name of the default error code policy to use.
TimeoutErrorMappingobject(see below)Error mapping for command timeout errors.
ErrorCodePoliciesarray(see below)Named policies for mapping PostgreSQL error codes to HTTP responses. Assign a policy to an endpoint using the error_code_policy annotation.

Error Mapping Object

Each error mapping has the following fields:

FieldTypeDescription
StatusCodeintHTTP status code to return.
TitlestringTitle field in response JSON. When null, the actual PostgreSQL error message is used.
DetailsstringDetails field in response JSON. When null, the PostgreSQL error code is used.
TypestringURI reference (RFC3986) identifying the problem type. When null, uses default. Set RemoveTypeUrl to true to disable.

Timeout Error Mapping

Configure the response when a command timeout occurs:

json
{
  "ErrorHandlingOptions": {
    "TimeoutErrorMapping": {
      "StatusCode": 504,
      "Title": "Command execution timed out",
      "Details": null,
      "Type": null
    }
  }
}

This maps command timeouts to HTTP 504 Gateway Timeout. Timeouts occur when a query exceeds:

  • The global NpgsqlRest.CommandTimeout setting, or
  • The per-endpoint command_timeout annotation

Error Code Policies

Define named policies for mapping PostgreSQL error codes to HTTP responses:

json
{
  "ErrorHandlingOptions": {
    "DefaultErrorCodePolicy": "Default",
    "ErrorCodePolicies": [
      {
        "Name": "Default",
        "ErrorCodes": {
          "42501": {"StatusCode": 403, "Title": "Insufficient Privilege", "Details": null, "Type": null},
          "57014": {"StatusCode": 205, "Title": "Cancelled", "Details": null, "Type": null},
          "P0001": {"StatusCode": 400, "Title": null, "Details": null, "Type": null},
          "P0004": {"StatusCode": 400, "Title": null, "Details": null, "Type": null}
        }
      }
    ]
  }
}

Default Error Code Mappings

PostgreSQL CodeNameHTTP StatusDescription
42501insufficient_privilege403 ForbiddenUser lacks required permissions
57014query_canceled205 Reset ContentQuery was cancelled
P0001raise_exception400 Bad RequestExplicit RAISE EXCEPTION in function
P0004assert_failure400 Bad RequestAssert statement failed

See PostgreSQL Error Codes for the complete list.

Response Fields

Type URL

When RemoveTypeUrl is false (default), error responses include a Type URL pointing to RFC documentation:

json
{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "Bad Request",
  "status": 400
}

TraceId

When RemoveTraceId is false, error responses include a TraceId for log correlation:

json
{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "Bad Request",
  "status": 400,
  "traceId": "00-abc123..."
}

Example Configuration

Production configuration with custom error mappings:

json
{
  "ErrorHandlingOptions": {
    "RemoveTypeUrl": false,
    "RemoveTraceId": true,
    "DefaultErrorCodePolicy": "Default",
    "TimeoutErrorMapping": {
      "StatusCode": 504,
      "Title": "Request timed out",
      "Details": "The database operation took too long to complete.",
      "Type": null
    },
    "ErrorCodePolicies": [
      {
        "Name": "Default",
        "ErrorCodes": {
          "42501": {"StatusCode": 403, "Title": "Insufficient Privilege", "Details": null, "Type": null},
          "57014": {"StatusCode": 205, "Title": "Cancelled", "Details": null, "Type": null},
          "P0001": {"StatusCode": 400, "Title": null, "Details": null, "Type": null},
          "P0004": {"StatusCode": 400, "Title": null, "Details": null, "Type": null},
          "23505": {"StatusCode": 409, "Title": "Conflict", "Details": "A record with this key already exists.", "Type": null},
          "23503": {"StatusCode": 400, "Title": "Invalid Reference", "Details": "Referenced record does not exist.", "Type": null}
        }
      }
    ]
  }
}

Development configuration with TraceId for debugging:

json
{
  "ErrorHandlingOptions": {
    "RemoveTypeUrl": false,
    "RemoveTraceId": false,
    "DefaultErrorCodePolicy": "Default"
  }
}

Next Steps

Released under the MIT License.