TokenPolice
Docs
SDK reference

Errors: TokenPoliceBlockedError

The one exception TokenPolice ever raises into your code, its fields, and exactly when it fires.

TokenPolice is fail-open by design: if anything inside the SDK or the collector goes wrong, your LLM call still runs. There is exactly one exception it will ever raise into your code — TokenPoliceBlockedError — and only on a deliberate block.

When it fires

Only when both dials say enforce: the SDK is firewall="enforce" and the rule that matched is set to Enforce, and that rule's decision is to block. In every other case — dry-run on either dial, a check timeout, a collector outage — nothing is raised and the call proceeds.

See Dry-run vs enforce for the full truth table.

Catching it

Wrap the call and read the structured fields.

import token_police as tp

try:
    resp = client.chat.completions.create(...)
except tp.TokenPoliceBlockedError as e:
    print(e.reason)     # human-readable reason
    print(e.rule_id)    # which rule blocked
    print(e.kind)       # what kind of block (e.g. "budget", a loop detector)
    print(e.trace_id)   # the trace this decision belongs to
import * as tp from "token-police";

try {
  const resp = await client.chat.completions.create(/* ... */);
} catch (e) {
  if (e instanceof tp.TokenPoliceBlockedError) {
    console.log(e.reason, e.ruleId, e.kind, e.traceId);
  }
}

The fields

PythonNodeWhat it is
reasonreasonHuman-readable reason for the block.
rule_idruleIdThe rule that produced the decision.
kindkindThe block category — e.g. "budget", or a loop-detector name.
trace_idtraceIdThe trace this run belongs to.

This is the only error to catch. Everything else about TokenPolice is fail-open — a network blip, a bad response, the collector being down: your call goes through untouched. Handling TokenPoliceBlockedError is all the error handling you need.

Next