Developer documentation
Troubleshooting
Last reviewed 31 August 2026
Troubleshooting
Start here:
cain doctor
It names the misconfiguration and prints the command that fixes it.
"not authenticated" / exit code 4
cain login
If it still fails, the key may be valid but the subscription inactive -- that
returns HTTP 402 and doctor reports it separately from a rejected key.
"could not reach the fabric" / exit code 3
cain status cain connect --endpoint https://cainstudio.online
Exit code 3 is deliberately distinct from 1: an outage is not a policy refusal.
When the fabric is unreachable every decision is ERROR, and under strict mode
that means every guarded call refuses. That is intended -- a network failure
between an agent and its authorization service is not consent.
Everything is allowed and I expected denials
Likely one of three things, all of which cain doctor reports:
1. The deployment is in shadow mode. Decisions are recorded, nothing blocks.
Check cain status for mode.
2. The stage you expected to block is advisory. cain status lists which
stages are enforcing.
3. The stage is enforcing but has nothing loaded. doctor reports
patterns_loaded: 0 for exactly this case -- enforcing with nothing to match.
Nothing is allowed
policy.default: denywith no rules that permit your action.cain policy test
will tell you.
- A revoked principal.
cain doctorreports principal status. - The fabric is unreachable and strict mode is on -- see above.
UNKNOWN verdicts
A stage could not answer. cain explain <id> names it. Common cause: the
ActionProof or agent-id service is down; doctor checks dependency reachability.
UNKNOWN is refused rather than allowed by design. If you need the looser
behaviour, enforcement.strict: false is the switch -- and doctor will warn
about it for as long as it is off, because it converts "we could not check" into
permission.
cain validate fails on a key I am sure exists
Unknown keys are errors, not warnings. Run cain validate --list-keys for the
accepted set. This is deliberate: a typo'd key that gets silently ignored is how a
config ends up looking stricter than it is.
"MCP calls are not being decided"
Your client is probably still reaching the server directly. Putting the gateway
in the path does not remove the direct route -- bind the server to localhost or a
network only the gateway can reach. cain doctor cannot detect this and does not
claim to.
The signature changed between reads
It should not; signing is deterministic. If it did, the decision record was
altered, which is the property the signature exists to reveal. `cain test --suite
evidence` checks this explicitly.