Failing well¶
The error category is not paperwork. KAI-C routes on it: a
transport_error is never retried, a model_error counts against the
adapter, an overloaded makes KAI-C back off and come back. Getting it
wrong turns one bad frame into a retry storm, or a busy adapter into one
the operator is told is broken.
What the facade classifies for you¶
| You raise | Becomes |
|---|---|
ValueError, KeyError |
400 transport_error, not retried |
Overloaded(retry_after_ms=…) |
503 overloaded, retried after the hint |
anything else, TypeError included |
500 model_error, logged with a traceback |
ServiceError(...) |
passed through exactly as you wrote it |
TypeError is deliberately on the model_error side. It almost always
means the handler itself is wrong — a None where a number was expected,
a bad call signature — and blaming the caller for that hid real bugs
behind a 400 with no traceback anywhere.
So the common cases need no error handling at all:
@adapter.on_image()
def detect(call):
if not call.image:
raise ValueError("a frame is required") # → 400
if _queue_depth() > 32:
raise Overloaded(retry_after_ms=250) # → 503
return _run(call.model, call.image) # anything else → 500
When to be explicit¶
Two categories the facade cannot infer, because only you know them:
if call.param("match_faces") and not _face_matching_permitted():
# The operator's policy, not a model failure. PERMISSION_DENIED
# tells KAI-C this will not succeed on retry either, and the
# message reaches the operator's audit log.
raise ServiceError(
ErrorCategory.PERMISSION_DENIED,
code="face_matching_refused",
message="Site policy does not permit face matching on this camera.",
transient=False,
http_status=403,
)
provider_error is the other: an upstream your adapter fronts is down.
The adapter is fine, its dependency is not, and it is transient — so
KAI-C should retry.
Backpressure is honest¶
Silently queueing turns a slow model into growing latency nobody can
see. Overloaded says so, with a number the caller can act on.
Full example:
04_errors_and_backpressure.py.