Failure modes and recovery
Developer Preview
This page defines every reason code in verdict schema version 1 and the builder response for each one.
Decision states
These reason codes describe a successful or unfinished evaluation rather than a policy failure.
reasonCode | Definition | Builder response |
|---|---|---|
allowed | Guardian completed evaluation and the exact proposed action satisfied the active policy. It is valid only with outcome: "approved". | Stop polling. Continue only if the SDK or MCP approval fields also agree, and only for the hash-bound action that was evaluated. |
pending | Guardian has not produced a terminal verdict. It is valid only with outcome: "pending". | Keep the action paused and poll the status resource with bounded backoff. A timeout remains blocked. |
If a client receives an unknown reason code, preserve the value and
humanReason for diagnostics, but do not treat it as approval. Branch on
outcome, and require the complete approved/allowed invariant before
continuing.
Cross-cutting failures
Cross-cutting failures may be returned with checks: [] because they happen
before a single policy check can explain the result.
reasonCode | Definition | Builder response |
|---|---|---|
decode_failure | Guardian could not safely decode, classify, or bind the proposed action to a supported operation. This is not proof that a configured policy limit was exceeded. | Inspect the decode step and redacted evidence. Correct or rebuild the action for a supported shape; do not widen the policy to make malformed input pass. |
data_unavailable | Policy, state, reference, sanctions, market-catalog, or price data required for a safe decision was missing, stale, unavailable, or unusable. The same code can also appear on a failed check. | Keep execution blocked. Identify the dependency from the failed check, humanReason, freshness metadata, and evidence; request a new verdict only after the dependency is usable. |
asset_identity_unresolved | A signed Hyperliquid market index does not exist in the trusted market catalogue for the action's network, so Guardian cannot map it to policy identity. | Confirm the network and market index. Rebuild the action against the current catalogue; never guess a symbol or substitute a different asset locally. |
Per-check failures
For these codes, the top-level reasonCode normally matches a failed item in
checks[]. More than one check can fail; the top-level code is the primary
failure, not the complete result.
checkId | Failure code | Definition | Builder response |
|---|---|---|---|
venue | venue_not_allowed | The decoded venue has no configuration in the active policy. | Route through an allowed venue or make a deliberate reviewed policy change, then request a new verdict. |
chain | chain_not_allowed | The EVM chain or Hyperliquid network is outside the venue policy's allowlist. | Correct the action's network or use an allowed one. Do not retry the unchanged action. |
contract_selector | contract_or_selector_not_allowed | The target contract is covered by contractAllowlist, but its decoded function selector is not permitted by that contract's entry. | Verify the target and selector against the intended deployment and function. An unlisted target is not_checked, so do not use this optional check as a deny-by-default contract guarantee. |
asset | asset_not_in_universe | A referenced token or resolved market is outside the policy's asset universe. | Correct the asset or use an allowed one. Never substitute a locally inferred asset identity. |
recipient | recipient_not_allowed | The effective recipient is neither allowlisted nor one of the agent's registered wallets. | Correct the recipient or review its registration and allowlist before submitting a new request. |
sanctions | sanctioned_address | At least one address touched by the action appears in the active sanctions or policy deny list. | Stop the action and escalate for compliance review. Never weaken sanctions controls to continue. |
side | side_not_allowed | The proposed buy or sell side is disallowed for the resolved asset. | Change the order intent or review the asset-side constraint; do not retry unchanged. |
slippage_guard | no_slippage_guard | A Uniswap swap lacks a non-zero minimum output or finite maximum input. | Rebuild the swap with an explicit protective bound and request a new verdict. |
execution_price_bound | no_execution_price_bound | A Hyperliquid order lacks a finite, positive limit price. | Add a reviewed execution-price bound and request a new verdict. |
sink_recipient | sink_recipient | The effective recipient is a known zero, burn, or dead address. | Correct the recipient. Treat an unexpected sink as a construction or routing incident. |
per_tx_cap | per_tx_cap_exceeded | The action's summed USD notional exceeds perTxCapUsd. | Reduce or split the proposed action only if that remains faithful to the user's intent; every new action needs its own verdict. |
outflow_24h | outflow_24h_exceeded | Retained venue spend in the rolling 24-hour window plus this action exceeds max24hOutflowUsd. | Wait for the window to move or reduce the action. Do not clear history or retry unchanged. |
leverage | leverage_cap_exceeded | A Hyperliquid leverage update requests a value above maxUpdateLeverage. | Lower the requested leverage or make a reviewed policy change before requesting another verdict. |
portfolio_leverage | leverage_cap_exceeded | A Hyperliquid order would push projected gross portfolio leverage above maxPortfolioLeverage. | Reduce the order or exposure. Re-evaluate against fresh account state and mark data. |
protocol_exposure | protocol_exposure_exceeded | A Hyperliquid order would push projected gross protocol exposure above maxExposurePerProtocol.hyperliquid. | Reduce the order or current exposure, then request a new verdict using fresh state. |
Any data-dependent check can fail with code: "data_unavailable" instead of
its policy-violation code. Read only the returned checks as evaluated:
not_checked is not passed, and an absent check did not necessarily run. For
a multi-leg action, legIndex identifies the zero-based decoded leg when the
field is present.
Degraded and stale data
A degraded result is terminal for that verification request:
outcome: "rejected" and reasonCode: "data_unavailable". It is not another
form of pending, and a cached row is not evidence that the dependency met the
check's freshness bound.
This abridged verdict shows a stale Hyperliquid mark blocking a configured per-transaction cap:
{
"outcome": "rejected",
"reasonCode": "data_unavailable",
"humanReason": "Per-transaction cap cannot be enforced — hyperliquid mark for ETH has invalid age or exceeds the 10000ms freshness limit.",
"triggeringPolicyField": "perTxCapUsd",
"checks": [
{
"checkId": "per_tx_cap",
"status": "failed",
"code": "data_unavailable",
"humanReason": "Per-transaction cap cannot be enforced — hyperliquid mark for ETH has invalid age or exceeds the 10000ms freshness limit.",
"triggeringPolicyField": "perTxCapUsd"
}
],
"dataFreshness": {
"overall": "cached",
"sources": [
{
"source": "hyperliquid:metaAndAssetCtxs",
"status": "cached",
"asOf": "2026-08-20T10:00:00.000Z",
"ageMs": 15342
}
]
}
}Use this order to identify the dependency:
Find the failed checks
Find each failed checks[] item with code: "data_unavailable". Its checkId,
humanReason, and triggeringPolicyField explain which guarantee could not be
enforced.
State snapshots can report stale, unavailable, never_fetched, or
skipped through the affected check's humanReason. For example,
portfolio_leverage or protocol_exposure can fail with
data_unavailable and state that the Hyperliquid source is stale. A state
source might not also appear in dataFreshness.sources[]; use the failed
check and its explanation as the source diagnosis.
Do not loop on a terminal degraded verdict. Wait for the named source to recover, then submit a new verification request for the current exact action. If the action, policy, or relevant state changed, the earlier verdict cannot be reused.
Agent API-key behavior
An agent API key identifies one agent and carries service-assigned default
scopes. The current issuance API accepts a name and optional expiry, not a
caller-selected scope set. Confirm the returned scope metadata includes the
permissions your integration requires. Use the key in the x-api-key header;
never place it in a URL.
The secret is returned only when a key is issued. Later key listings expose metadata such as the key ID, name, scopes, active state, expiry, creation time, and last-used time, but not the secret. Revoking a key disables that credential without erasing the agent's existing verdict history.
Planned rotation
For planned rotation, issue the replacement before revoking the old key:
Issue the replacement
Issue a named replacement for the same agent with an intentional expiry. Verify its service-assigned scopes before deployment.
Deploy the new secret
Store and deploy the new secret through the approved secret manager without printing or logging it.
Test the replacement
Send one controlled verification with the new key. Move new traffic only after its submit and status-read path succeeds.
Suspected exposure
If a key may be exposed, revoke the exposed key first. Pause new submissions, remove the secret from every runtime and delivery system, issue a replacement, and redeploy it through the normal secret path. Review the agent's verdict history from the earliest suspected exposure time and investigate unfamiliar request hashes or actions. Request fresh verdicts for any in-flight action whose status or integrity is uncertain.
| Response | Meaning | Builder response |
|---|---|---|
401 | The key is absent, invalid, expired, or revoked. | Stop requests and replace or re-authenticate the credential. Do not retry with the same value. |
403 | Authentication succeeded, but scope, request ownership, agent identity, or registered wallet does not match. | Keep execution blocked and correct the configuration. Rotating an otherwise valid key does not fix an ownership or wallet mismatch. |
Incident response
Treat suspected credential exposure, persistent service failures, repeated degraded verdicts, and an unexpected verdict/action mismatch as incidents.
Pause execution
Keep signing and venue submission paused. Reconcile an uncertain POST before
attempting another submission; the preview API has no idempotency key.
Capture the verdict context
Capture the requestHash, verdict timestamp, policyVersion, outcome, primary
reason, failed checks, and freshness rows. Include redacted evidence only.
Record the environment safely
Record the agent and environment, but never include the API-key secret in logs, tickets, chat, screenshots, or analytics.
See the API reference for the complete verdict shape and HTTP status handling.