Skip to main content

Errors

jes raises a small family of exceptions, all under JesError, for problems in your setup or in the backend. Problems in the text never raise.

Its job​

The errors draw one line: your code versus the text you check.

  • If the setup is wrong, jes raises: a missing threshold, a judgment with no model, a broken custom policy. You fix the code. Most of these fire when you build the guard, before any traffic.
  • If the text is a problem, jes returns a result with a finding: too long, invalid Unicode, an injection, too many redactions. Your code branches on result.ok, as it does for every other check.
  • The backend sits in between. A timeout or a 429 isn't your bug, and it isn't the text's fault. You choose how it surfaces with on_backend_error.

Mental model​

JesError
├── ConfigError agent hooks: bad config file, payload, or env
├── PolicyError bad setup, raised when you build things
├── PolicyExecutionError a custom policy broke its contract mid-check
├── RedactionError wrong store, bad scope, blob won't load
└── BackendError the model call failed (reason says why)
└── DeadlineExceeded the check ran past deadline_s

Messages carry metadata only, never the checked text or a provider's response body. Every jes error is safe to log.

Using it​

Setup errors surface right away. Build guards at startup, so they fail before traffic:

from jes import Guard, PolicyError
from jes.policies import injection

try:
guard = Guard([injection(threshold=0.72)]) # no model=
except PolicyError as error:
print(error) # judgment injection has no model; pass model= to the guard

Backend errors depend on on_backend_error:

on_backend_errorA failed model callok
"raise" (default)The check raises BackendErrorn/a
"block"A blocking backend_error findingFalse
"allow"A flag backend_error findingFalse

With "block" or "allow" the result is incomplete, so ok is false either way. "allow" only matters if you act on decision instead of ok.

With the default, catch BackendError where you call the check:

from jes import BackendError

try:
result = guard.check_input(user_text)
except BackendError as error:
log.warning("jes backend failed: %s %s", error.backend, error.reason)
return refuse()

Good to know​

  • Don't catch PolicyError or PolicyExecutionError per request. They mean the code is wrong. PolicyExecutionError always raises, whatever on_backend_error says.
  • A missing threshold= is a TypeError. The factories make it a required keyword, so Python rejects the call before jes runs.
  • error.reason is a stable string, such as timeout, rate_limited, unauthorized, or deadline_exceeded. Branch on it for retries. The full list is in the reference.
  • except JesError catches everything jes raises, for a single catch-all at a boundary.
  • The Python library never raises ConfigError. Only the agent hooks do.

Next​