Skip to content

Latest commit

 

History

History
55 lines (46 loc) · 3.24 KB

error-flow.md

File metadata and controls

55 lines (46 loc) · 3.24 KB

Consistent error flow

Status: current implemented v1 behavior. The accepted documentation-only successor design is the six-digit standard, exception/boundary guide, and migration plan. Those documents do not describe shipped runtime behavior.

Every REST request passes through the service's request-ID filter and boundary validation. The filter accepts a bounded alphanumeric X-Request-Id or creates one, returns it on every response, and makes it available to logs and tracing.

All REST services import libs/errors. Its advice maps framework and domain failures to application/problem+json with this shape:

{
  "type": "https://squarewise.example/problems/request_validation_failed",
  "title": "Validation failed",
  "status": 422,
  "code": "VALIDATION_ERROR",
  "numericCode": "911101",
  "errorName": "REQUEST_VALIDATION_FAILED",
  "messageKey": "error.request.validation_failed",
  "requestId": "req_123",
  "detail": "One or more request parameters failed validation.",
  "timestamp": "2026-10-08T14:00:00Z",
  "violations": [{"field": "totalMinor", "message": "must be greater than 0", "messageKey": "validation.positive", "rejectedValue": -50}]
}

Clients branch on high-level category code (e.g. VALIDATION_ERROR, BUSINESS_RULE_VIOLATION, NOT_FOUND, STATE_CONFLICT, RESOURCE_GONE, AUTHENTICATION_ERROR, AUTHORIZATION_ERROR, RATE_LIMIT_EXCEEDED, MALFORMED_REQUEST, INTERNAL_ERROR), use messageKey for frontend internationalization (i18n), and use errorName / numericCode for exact domain identity, telemetry, and observability.

Generic HTTP 400 is strictly reserved for malformed request syntax / unparseable payloads (REQUEST_BODY_MALFORMED, GRAPHQL_OPERATION_INVALID). Semantic validations, Bean validation, and business rule violations use HTTP 422 (Unprocessable Content), while expired tokens and cursors use HTTP 410 (Gone).

Rate-limit denials and fail-closed limiter-store decisions use HTTP 429 with the catalogued RATE_LIMIT_EXCEEDED category. The REST boundary includes a bounded Retry-After value of 60 seconds for this code; limiter failures must not be translated into an application 5xx or an unstructured gateway error. The BFF uses the same catalog in GraphQL errors[].extensions.code: resolver/upstream 429 responses and query depth/complexity rejections use RATE_LIMIT_EXCEEDED, while other upstream 4xx responses retain their corresponding 4xx code.

Request validation is mandatory on every command/query DTO. Domain invariants remain mandatory after transport validation; a valid JSON shape can still be an invalid expense or unauthorized operation.

The complete GraphQL extension and WebSocket lifecycle contract is defined in contracts/graphql/errors.graphqls and contracts/graphql/README.md. Valid upstream Problem Details preserve code, required numericCode and errorName, requestId, source, timestamp, and bounded violations. An unparseable upstream response receives a BFF-owned protocol error rather than a status-derived or fabricated upstream identity. WebSocket lifecycle failures use close codes 4401, 4403, 4408, and 4429.