What this is about
Every response has an HTTP status code, a three-digit number. The first digit tells you who has to act:
- 2xx: It worked.
- 4xx: The request does not fit. The client has to change something before a new attempt makes sense.
- 5xx: Something went wrong in the server. The client cannot improve anything about the request.
Where the codes arise
A request passes through several stations. Each station has its own codes:
-
CIASFilter chainIs there a valid token? Can the tenant be determined?↳ no 401 token invalid · 403 no token or tenant refused
-
CDMSRoutingDoes this path exist?↳ no 404 without
messageKey -
CDMSREST layerCan the body be read? Are
dataandresponsethere?↳ no 400 · 413 upload too large -
CDMSSystem layerRole, visibility, relations, field rules, hooks↳ no 403 · 404 · 400 · 422
-
DatabasePersistenceDoes the database accept the change?↳ no 409 value already taken or object still referenced · 409 concurrent change · 400 value does not fit the column · 503 database unreachable
- 200 with
data, the change is committed
When the role and when visibility is checked first is described in 401, 403 or 404?.
The matrix
| Code | means | typical situations and messageKey | try again? |
|---|---|---|---|
| 200 | successful | read, search, create, change, delete, rollback. Special case: created, but not read back (CDMS_CREATE_SUCCEEDED_READ_FAILED) | – |
| 400 | request faulty | JSON not readable, value does not fit the field, response or data missing, filter with a wrong value, creating through a relation not allowed, value does not fit the database column | only after a correction |
| 401 | token invalid | token expired, broken or wrongly signed | after renewing the token, once |
| 403 | not allowed | no token, tenant refused, role missing (missing-permission|<role>), tenant switch not allowed | no |
| 404 | not found | object does not exist or is invisible to you, singleton not created yet, path unknown | no |
| 409 | conflict | unique value already taken (already-exists), object still referenced (database-integrity-failed), two requests write new content into the same file object at the same time | for already-exists and database-integrity-failed only after a correction, otherwise after reading again |
| 413 | upload too large | a file (file-too-large|<bytes>), all files together (request-too-large|<bytes>) or the number of parts (too-many-parts|<count>) above the limit | only after a correction |
| 422 | content breaks rules | field rules violated (validation-failed with violations), hook refuses, profile attribute missing | only after a correction |
| 500 | server error | unexpected error in the server or an error in the project’s setup | usually pointless |
| 503 | database unreachable | the database server does not respond, the connection drops, a lock is not released in time, the database aborts a deadlock | after a pause |
What is stored after each code and how you retry is described in May the client retry?.
200: successful
Every successful request returns 200, including a create and a delete. Codes like 201 or 204 do not exist. A delete answers with an empty body, everything else with data. See The response format.
There is one special case: in LENIENT mode a create can succeed while only the read-back fails. Then you get 200 with a body in error shape, the messageKey CDMS_CREATE_SUCCEEDED_READ_FAILED and the id of the new object. The object is stored, do not create it again. See Create and read back.
400: the request is faulty
400 means: CDMS cannot execute the request as it is. The messageKey tells you what does not fit, often with the path or field after it.
| Area | messageKey | Page |
|---|---|---|
| body not readable | malformed-json, unreadable-body | Validation |
| value does not fit the field | invalid-value|<path>, e.g. text in a number field | Validation |
| part of the request missing | response, missing-data, missing-id, missing-parameter | Reading an object |
| path value has the wrong type | invalid-parameter|<name>, e.g. an id that is not a UUID | – |
| filter or sorting wrong | wrong-value-in-where|…, wrong-uuid-in-where|…, like-needs-text|…, wrong-order-element-exception | When a filter does not fit |
| relation does not allow creating | recursive-create-not-allowed|<field> | The four cases |
| subtype missing or unknown | missing-type-for-abstract-field|…, unknown-type-for-abstract-field|… | Abstract models |
| the database does not accept a value, e.g. longer than the column or empty in a required column | constraint-violation | Validation |
| a reference points, when saving, to an object that does not exist (any more) | unknown-reference | The four cases |
| singleton already exists | object-already-exists|use-update | Singleton |
| file object without a matching file | file-part-missing|<name>, file-name-missing | Uploading |
| tenant missing | CDMS_TENANT_REQUIRED | Where the tenant of a request comes from |
401 and 403: who you are and what you may do
401 only comes from the filter chain: the token is expired, broken or wrongly signed. The response has no body, but the header WWW-Authenticate: Bearer error="invalid_token". Renew the token and retry the request once.
403 means: this request is not allowed for you. There are three sources:
| Source | how you recognize it | Example |
|---|---|---|
| filter chain, no token | body without messageKey | header Authorization missing |
| filter chain, tenant | field error with cias.authentication.… | cias.authentication.tenant-unresolved |
| CDMS | messageKey | missing-permission|hr-employee-read, without strict mode missing-create-role and others, CDMS_TENANT_SWITCH_NOT_AUTHORIZED |
See Access without a token, Model roles and Strict mode.
404: not found
404 with a messageKey means: the object does not exist, or you may not see it. CDMS deliberately does not tell these apart. Typical keys are not-found, not-found|<Dto>|<id>, missing-object|… for a missing child in a relation, and no-data-exists|use-create for a singleton that does not exist yet.
404 without a messageKey means: the path does not exist. Usually the model path is misspelled, or the model does not have this endpoint. See Why invisible objects return 404 and Which endpoints a model has.
409: conflict
409 means: the change does not fit the data that is already stored. Nothing is stored. There are three cases:
| Situation | messageKey | what to do |
|---|---|---|
a unique value or the id is already taken | already-exists | do not retry: the value exists already. Choose another value or change the existing object |
| another object still points to this one when saving, for example because the reference came into being at the same time. References through the model are cleared by CDMS itself on delete, see Dependent objects (cascades) | database-integrity-failed | do not retry: remove the reference first |
| two requests write new content into the same file object at the same time, and the second one loses | CDMS_OPTIMISTIC_LOCK_CONFLICT | read the object again, then try again |
The concurrent write conflict only exists for file models; for all other models the last change wins without an error. See Concurrent changes.
422: the content breaks rules
422 means: the request is built correctly, but its content breaks a rule.
When: required field empty, text too long, pattern, minimum or maximum value, date
messageKey validation-failed. violations holds all violations of the request, each with field path and rule.
Result: See Getting validation errors into the form.
When: The project's business logic throws a validation error.
layer is hook, the hook chooses the messageKey. There is no violations.
Result: See When a hook fails.
When: An attribute filter needs a value from your profile, and it is missing or empty.
missing-attribute-on-profile|<attribute> or empty-attribute-on-profile|<attribute>, without violations.
Result: Not the data is wrong, but the person's profile. See Attribute filter.
500: error in the server
500 means: something happened in the server that the client cannot fix. There are two kinds:
- Unexpected error. The
messageKeyisdetails see logfiles,layerisundefined. The cause is in the server log. - Error in the setup. The project is set up wrongly, and the
messageKeynames it. Examples:unresolvable-mandatory-filter|…for a filter on a field that does not exist, andCDMS_TENANT_DATASOURCE_NOT_FOUNDwhen the tenant’s database is missing.
An unexpected exception in a hook also ends with 500. A retry does not help in any of these cases. Pass status, messageKey and time on to the team.
503: the database cannot be reached
503 means: the database cannot serve the request right now. Nothing is stored, the transaction has been rolled back. This is a disruption, not a fault in your data: a retry after a pause can succeed.
| Situation | messageKey |
|---|---|
| the tenant’s database server cannot be reached | CDMS_TENANT_DATASOURCE_UNAVAILABLE |
| the connection drops during the request | database-unavailable|connection |
| a lock on the object is not released in time | database-unavailable|lock-timeout |
| the database aborts the request because of a deadlock with another one | database-unavailable|deadlock |
If the database instead rejects a change because of the data already stored, the answer is 409, and an unchanged retry fails the same way. See above.
Refusals when uploading
When uploading files, CDMS refuses a request with 400 if two parts have the same file name (duplicate-filenames|<name>), a part has no file name (missing-filename) or the multipart body cannot be read (malformed-multipart). If a file, the whole request or the number of parts is too large, the answer is 413, and the messageKey names the limit, e.g. file-too-large|26214400 (bytes). Check names and size in the client already. See Uploading and Size limits.
Pitfalls
Where to go next
- How an error response is built: The error format
- The three codes that are often mixed up: 401, 403 or 404?
- What is stored after an error: One request, one transaction