CodamAIDocs
Topicdone

The error format

Which fields an error response has, and what a client should branch on.

Variants
Error response from CDMSValidation error with violationsRefusal by the filter chainResponse without a bodyStatus 200 in error shape (LENIENT)

What this is about

When a request goes wrong, CDMS answers with an error status (400 and above) and an error response. The error response is a small JSON object without data. It tells you what happened, in a form a program can evaluate. CIAS answers in exactly the same shape.

The response contains no sentence for people, but a key. Your frontend turns it into the text the user sees, in the user’s language.

An error response, labeled

The read role is missing
Request
POST /api/rest/hr/employee/read/5a2b…
{ "response": ["name"] }
Response 403, labeled
{
  "messageKey": "missing-permission|hr-employee-read",
                 └── key ──────┘ └── detail ──┘  ← branch on this
  "code":       "403",                          ← status as text
  "layer":      "validation"                    ← layer, for debugging only
}
Fieldalways present?Meaningin the client
messageKeyyesfixed key, often with details after |branch on this
detailonly in the server’s debug modetechnical text of the causenever show it, never evaluate it
codeyesthe HTTP status as text, e.g. "422"same as the status of the response
layeryeslayer in which the error occurredfor debugging only
violationsonly for validation errorsall violated field rules with pathmap them to the form fields
idonly in the LENIENT special caseid of the created objectkeep it, read later
stacktraceonly in the server’s debug modetechnical call stacknever evaluate it

The messageKey in detail

The messageKey has the form key|detail|detail. Before the first | is the key, i.e. the kind of problem. After it, depending on the error, come details such as a field name, a model name, a role name or an id. Values you send in fields or filters are never in it.

messageKeykeydetails
missing-permission|hr-employee-readmissing-permissionthe missing role
invalid-value|data.amountinvalid-valuepath of the field in the body
wrong-value-in-where|amountwrong-value-in-wherethe field of the filter, never the value
recursive-create-not-allowed|employeesrecursive-create-not-allowedthe relation
not-found|Person|5a2b…not-foundmodel and id
validation-failedvalidation-failednone, the details are in violations
optimistic-lock-conflictoptimistic-lock-conflictnone

This is how you get the key in the client:

Separating key and details
TypeScript
const [key, ...details] = body.messageKey.split('|');
// key     = "missing-permission"
// details = ["hr-employee-read"]
Branching
switch (key) {
  case 'missing-permission': …  // role missing
  case 'not-found':          …  // object gone or invisible
  case 'validation-failed':  …  // violations into the form
  default:                   …  // general message
}

All CDMS keys are written in lowercase with hyphens, such as tenant-required or missing-id. Compare the key character by character, exactly as it is.

Three shapes of error bodies

Not every refusal comes from CDMS itself. The CIAS filter chain runs first. It answers in the same shape, and its key starts with cias.authentication.. Some refusals have no body at all.

Who answered?
CDMS
body with messageKey
  • messageKey, code, layer
  • every refusal from the role check on
  • also 400 for a request that cannot be read
Filter chain, tenant
403 with messageKey, key cias.authentication.…
  • {"messageKey": "cias.authentication.tenant-unresolved", "code": "403", "layer": "api"}
  • the tenant cannot be determined, is not served or is missing
  • the same shape as CDMS
without a body
no CDMS JSON
  • 401: token invalid or expired, header WWW-Authenticate
  • 403: no token at all
  • 404: the path does not exist

More about the refusals of the filter chain in Access without a token and 401, 403 or 404?.

Validation: violations

Only a validation error has a list violations. Each entry names the field with its path and the violated rule:

Two required fields are missing
Request
POST /api/rest/crm/customer/create
{ "data": { "name": "" }, "response": ["id"] }
Response 422
{
  "messageKey": "validation-failed",
  "code": "422",
  "layer": "API",
  "violations": [
    { "field": "name",  "rule": "cannot-be-empty" },
    { "field": "email", "rule": "cannot-be-null" }
  ]
}

How to map the entries to the form fields is described in Getting validation errors into the form. Which rules exist: Validation.

The special case: 200 in error shape

After a create in LENIENT mode, creating can succeed while only the read-back fails. Then you get status 200, but a body in error shape with the id of the new object:

Created, but not read back
Response 200
{
  "messageKey": "create-succeeded-read-failed",
  "code": "200",
  "layer": "system",
  "id": "5a2b…"
}
What the client should do
The object exists.
Keep the id and read it later,
do NOT create it again.

See Create and read back: STRICT or LENIENT.

How a client evaluates it

Evaluating a response
  1. 1
    Client
    Status 2xx?
  2. 2
    Client
    yes, and messageKey is create-succeeded-read-failed → created, keep the id
  3. 3
    Client
    yes, otherwise → use data
  4. 4
    Client
    no → read the body if there is one. Does it have a messageKey?
  5. 5
    Client
    yes → evaluate the key before the first |, for 422 also violations. If it starts with cias.authentication., the filter chain has already refused, for example because of the tenant
  6. 6
    Client
    no → decide by status: 401 renew the token, 403 without a token sign in, otherwise a general message

Pitfalls

Where to go next

Search