Failures and limits
Every result has two fields that together decide ok:
decisionis"block"when any finding blocks, and"allow"otherwise.completeis false when a configured transform or judgment did not finish.
ok is decision == "allow" and complete. Branch on ok, or forward
onward. onward is a refusal whenever ok is false, including on
fail-open paths, and it never contains the checked text.
Backend errors
A judge call can fail: a timeout, a rate limit, a TypeSafe error, a network
failure, a backend that returns nothing, or answers that are missing or don't
match the question. The judge lists the
BackendError reason for each.
Choose the behavior with Guard(..., on_backend_error=...):
| Mode | What happens | decision | complete | ok |
|---|---|---|---|---|
"raise" (default) | The check raises BackendError | n/a | n/a | n/a |
"block" | Adds a backend_error block finding | block | False | False |
"allow" | Adds a backend_error flag finding and omits the failed scores | allow unless something else blocks | False | False |
"allow" is an explicit fail-open. It doesn't add a block for the failure,
but the result is still incomplete, so ok is false.
Deadlines
deadline_s (default 30 seconds) is a per-check duration. A check sends its
requests to the judge in parallel, up to Limits.max_concurrency at once
across the guard. Requests still running at the deadline count as backend
errors: DeadlineExceeded, a subclass of BackendError. It follows
on_backend_error with the label deadline_exceeded. AsyncGuard cancels
those requests, and also cancels them when the caller cancels the check.
Guard stops waiting for them and returns.
Transforms check the deadline between steps. A transform cannot interrupt a synchronous third-party call that is already running, such as a Presidio analysis. jes applies the deadline outcome when the call returns.
Resource caps
Set the caps with Guard(..., limits=Limits(...)):
from jes import Guard, Limits
guard = Guard(policies, model="jev-latest", limits=Limits(max_input_bytes=65_536))
Size and count problems are findings, not exceptions. They block with
complete=False before more work is scheduled. Examples:
| Finding | Cause |
|---|---|
input_too_long | The text exceeds max_input_bytes |
normalized_too_long, invalid_unicode | A transform grew the text to over four times its limit, or the text has a lone surrogate |
context_too_long, too_many_context_items | The context exceeds its caps |
text_too_long | A whole_text judgment does not fit the judge's max_request_bytes |
too_many_chunks, too_many_items, too_many_requests | Chunk, item, or request caps were reached |
too_many_redactions, redaction_store_full | One check replaced over max_redactions values, or the store is full |
restored_output_too_large | Restoring placeholders grew the reply to over four times max_input_bytes |
Two findings only flag: context_dropped, when an "optional" context does
not fit next to the text, and history_truncated, when the oldest history
entries were left out to make it fit.
The seven caps and their defaults are in Limits.
Exceptions
| Exception | When |
|---|---|
PolicyError | Construction: duplicate names, missing threshold, an invalid limit, and so on |
PolicyExecutionError | During a check: a custom policy broke its contract. Always raised. |
RedactionError | A store or scope mismatch, or a serialized blob fails to authenticate |
BackendError | A transport failure or malformed answer, when on_backend_error="raise" |
DeadlineExceeded | A subclass of BackendError |
The runnable version is Failure and limits cookbook page.