REST error catalog
Every status code a REST channel returns, what causes it and which page owns the fix.
Every response a channel produces has exactly one source. This page lists each status code, what triggers it and what to check. All error bodies include the request's CID, the correlation id that finds the same request in the server log.
The catalog
| Status | Cause | Where the fix is |
|---|---|---|
| 400 | The service raised BadRequest, or a request did not match the service's data model | Error handling |
| 400 | A group-protected channel received both Basic Auth and an API key in one request - one credential per request | Security groups |
| 400 | An outgoing connection the service used timed out or could not connect - the body names the timeout or the connection error | Calling REST APIs |
| 401 | The channel's security definition rejected the request - wrong credentials, missing credentials or an expired token | Authentication |
| 403 | The channel is secured with security groups and the credential matched no member of any group | Security groups |
| 404 | No channel matches the URL path - the body is URL not found (CID:...) | Channels |
| 404 | The channel exists but is inactive - an inactive channel answers 404, not 503 | Channels |
| 404 | The service raised NotFound | Error handling |
| 405 | The HTTP method is outside the server's [http] methods_allowed list - the shipped default is GET, POST, DELETE, PUT, PATCH, HEAD and OPTIONS | URL path matching |
| 405 | Channels exist at the path but none accepts this method - the response includes an Allow header listing the methods that work | URL path matching |
| 409 | The service raised Conflict | Error handling |
| 429 | Rate limiting - the response includes Retry-After, and X-RateLimit-Limit with X-RateLimit-Remaining when the limit comes from a security definition | Rate limiting |
| 500 | The service raised an exception no handler translated - the full traceback is in the server log under the request's CID | Error handling |
| 500 | The channel's service is not deployed on the server | Hot deployment |
| 503 | The service raised ServiceUnavailable | Error handling |
Success codes with a story
| Status | Cause |
|---|---|
| 204 | A CORS preflight from an allowed origin - answered before authentication runs |
| 304 | The request's If-None-Match matched the cached response's ETag |
The 204 preflight is documented under CORS and the ETag behavior under response caching.
The 401 versus 403 rule
A channel secured with a security definition answers failed authentication with 401, and the response includes WWW-Authenticate when the scheme defines a challenge - Basic realm="..." for Basic Auth and Bearer for bearer tokens. API keys and mTLS send no challenge header.
A channel secured with security groups answers 403 instead, for a wrong credential and for a missing one alike.
Exceptions and their statuses
A service controls its channel's status code by raising one of the exception classes from zato.common.exception:
# -*- coding: utf-8 -*-
# Zato
from zato.common.exception import BadRequest, Conflict, Forbidden, NotFound, \
ServiceUnavailable, TooManyRequests, Unauthorized
from zato.server.service import Service
class GetUser(Service):
name = 'demo.rest.get-user'
def handle(self) -> 'None':
user_id = self.request.http.params['user_id']
user = self.invoke('demo.user.get-by-id', user_id=user_id)
if not user:
raise NotFound(self.cid, f'No such user: {user_id}')
self.response.payload = user
| Exception | Status |
|---|---|
BadRequest | 400 |
Unauthorized | 401 |
Forbidden | 403 |
NotFound | 404 |
MethodNotAllowed | 405 |
Conflict | 409 |
TooManyRequests | 429 |
InternalServerError | 500 |
ServiceUnavailable | 503 |
Any other exception, Python built-ins included, surfaces as 500. Whether the 500 body contains the exception's text or a generic message is the server's [misc] return_tracebacks setting, whose shipped default is to include it.
When there is no response at all
Two cases close the connection without any HTTP response, both by design:
- A request denied by a CIDR rule of rate limiting - the socket closes at once, imitating a dropped packet
- A request that is not well-formed HTTP - malformed framing, duplicate
Content-LengthorAuthorizationheaders, or a body over the server's size ceiling
See also
| Page | What it covers |
|---|---|
| Error handling | Raising the exceptions this catalog maps to status codes |
| Authentication | The security definitions behind the 401 responses |
| Security groups | The group-secured channels behind the 403 responses |
| URL path matching | The routing decisions behind 404 and 405 |