Errors — keystoneauth — branch stable/2026.2
Branch
stable/2026.2@1cd5400202c6— repository https://opendev.org/openstack/keystoneauth — analysed on 2026-10-28
keystoneauth turns everything into exceptions that derive from ClientException (keystoneauth1/exceptions/base.py:17). Its callers (clients, services, middleware) catch these classes. The status-to-class mapping and the reading of error bodies are therefore contracts with every OpenStack service.
1. HTTP responses ≥ 400 → from_response (keystoneauth1/exceptions/http.py:445-531)
Error body (only if Content-Type starts with application/json):
| Format | Fields read | Typical services |
|---|---|---|
{"error": {"message", "details"}} | message, details | Keystone (which also sends code and title, not read) |
{"errors": [{"title", "detail"}, …]} (API-SIG) | errors[0].title as the message, errors[0].detail as the details; "Multiple error responses, showing first only: " prefix if there are several | Placement, Ironic… |
| other JSON | message "Unrecognized schema in response body." | — |
text/* | the text as the details | — |
Headers:
x-openstack-request-id→request_id;Retry-After(seconds) →retry_after;- **401 +
Openstack-Auth-Receipt** → **MissingAuthMethods** (MFA receipt), whose body must holdreceipt.methods,receipt.expires_atandrequired_auth_methods(keystoneauth1/exceptions/auth.py:23-32).
Class by status: 400 BadRequest, 401 Unauthorized, 402, 403 Forbidden, 404 NotFound, 405 MethodNotAllowed, 406, 407, 408, 409 Conflict, 410, 411, 412, 413 RequestEntityTooLarge, 414, 415, 416, 417, 422, 429 TooManyRequests, 500 InternalServerError, 501, 502, 503 ServiceUnavailable, 504, 505 (keystoneauth1/exceptions/http.py:117-415). Any other 4xx gives HTTPClientError, any other 5xx HttpServerError.
2. Errors that do not come from an HTTP status
| Class | Situation | Source |
|---|---|---|
ConnectFailure, ConnectTimeout (retriable), SSLError, UnknownConnectionError | network failure, timeout, TLS error; connect_retries retries the first two only | keystoneauth1/exceptions/connection.py:26-48, keystoneauth1/session.py:1163-1230 |
AuthorizationFailure | no method given, or several scopes at once | keystoneauth1/exceptions/auth.py:19, keystoneauth1/identity/v3/base.py:181-199 |
InvalidResponse | the response to POST /v3/auth/tokens is not JSON, or has no token | keystoneauth1/exceptions/response.py:21, keystoneauth1/identity/v3/base.py:249-256 |
DiscoveryFailure, VersionNotAvailable | no usable version document (version hack disabled), or requested version absent | keystoneauth1/exceptions/discovery.py:32-58, keystoneauth1/discover.py:1444-1520 |
EndpointNotFound, EmptyCatalog | no matching endpoint in the catalog; empty catalog | keystoneauth1/exceptions/catalog.py:19-27, keystoneauth1/access/service_catalog.py:478-540 |
MissingRequiredOptions, NoMatchingPlugin, UnsupportedParameters | plugin configuration (loading) | keystoneauth1/exceptions/auth_plugins.py:31-85 |
Oidc*, InvalidOidcDiscoveryDocument | OIDC identity provider (discovery, endpoints, device-code timeout) | keystoneauth1/exceptions/oidc.py:26-56 |
TypeError "Specifying a 'X.latest' microversion is not allowed." / "microversion … was requested but no service_type …" | misuse of microversions | keystoneauth1/session.py:683-726 |
3. Logging
Requests and responses are logged at DEBUG, through a separate logger keystoneauth.session.request-id when split_loggers is enabled. Authentication bodies are not logged (log=False on POST /auth/tokens), and the Authorization, X-Auth-Token, X-Subject-Token and X-Service-Token headers are replaced in the logs by {SHA256}<hash> (keystoneauth1/session.py:504-517). A redirect without Location logs a WARNING "Failed to redirect request to %s as new location was not provided." (keystoneauth1/session.py:1259-1263).
Source: reverse-spec-keystoneauth/02-errors_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.