API errors¶
Every refusal of the REST API is an RFC 9457 problem
document. Read detail: it is the sentence written for whoever made the request.
{
"title": "Bad Request",
"status": 400,
"detail": "Scheme \"ftp\" is not allowed. Expected https, ssh or git.",
"instance": "/api/v1/repositories"
}
| Member | Always there | Meaning |
|---|---|---|
status |
yes | The HTTP status, repeated. |
title |
yes | The status's standard phrase. Not meant to be shown on its own. |
detail |
yes | What went wrong, in words meant to be displayed as they are. |
instance |
yes | The path that was requested. |
retryAfterSeconds |
on a 429 | How long to wait. The Retry-After header carries the same number. |
correlationId |
on a 500 | A reference to quote to your administrator; also found in detail. |
The content type is application/problem+json, including for a request the web server rejects
before the application sees it: a URL the security firewall refuses — //, an encoded .., a
; — and one the servlet container cannot decode, such as a lone % or an encoded /. Both are
a 400 whose detail says which kind of URL was refused; neither is an HTML page, and neither
names the server or its version. One exception remains: a failure thrown before any route is
reached is answered by the error page with the same members, as application/json unless the
client asks for application/problem+json in Accept.
What each status means¶
| Status | When |
|---|---|
| 400 | The request is malformed or a value in it is refused: a field missing, a URL with a scheme that is not allowed, a parameter of the wrong type, a body that is not JSON. Correct it and send it again. |
| 401 | No credential, or one that is not valid. Sign in again, or check the key. |
| 403 | The credential is valid and may not do this: the role does not allow it, a password change is owed, or the key or agent credential is not accepted on this route. The detail does not name the roles that would be. |
| 404 | The route does not exist, or what the path names does not — or it exists and you may not see it. The two read the same, in the same words, on purpose: a different answer would confirm that a repository, a scan or an issue you were not given exists. |
| 405 / 406 / 415 | Wrong method, an Accept the route cannot answer, a body in a media type the route does not read. |
| 409 | The request conflicts with the current state and may succeed later unchanged: a scan already queued, a solution that still holds projects, an OWASP review that cannot run yet. |
| 412 | The deployment is missing something an operator sets: the encryption key, a credential an agent cannot receive. |
| 413 | The body is larger than the route accepts. The detail names the ceiling. |
| 422 | A destination refused by the outbound policy. |
| 429 | Too many attempts from this address or with this key. Wait retryAfterSeconds. |
| 500 | A failure nobody wrote a sentence for. The detail says only that it happened and quotes a correlationId; the full error is in the control plane's log under that reference. |
| 503 | Transient: too many sign-ins awaiting their second factor. Try again in a few minutes. |
A 500 never explains itself¶
A 500 does not carry the message of what failed. That message was not written for a client — it
may name a table, a column, a file on the host or a library's internals — so it stays in the log.
To investigate, search the control plane's log for the correlationId:
SCIM¶
/scim/v2/Users answers a refused value, and a protected account, in the error schema of
RFC 7644 §3.12, because that is what a
directory client parses; a filter it does not evaluate is 400 with scimType invalidFilter. Every other refusal on the SCIM routes is a problem document as above.