Skip to content
LogoLogo

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.

reasonCodeDefinitionBuilder response
allowedGuardian 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.
pendingGuardian 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.

reasonCodeDefinitionBuilder response
decode_failureGuardian 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_unavailablePolicy, 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_unresolvedA 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.

checkIdFailure codeDefinitionBuilder response
venuevenue_not_allowedThe 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.
chainchain_not_allowedThe 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_selectorcontract_or_selector_not_allowedThe 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.
assetasset_not_in_universeA 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.
recipientrecipient_not_allowedThe 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.
sanctionssanctioned_addressAt 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.
sideside_not_allowedThe 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_guardno_slippage_guardA 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_boundno_execution_price_boundA Hyperliquid order lacks a finite, positive limit price.Add a reviewed execution-price bound and request a new verdict.
sink_recipientsink_recipientThe 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_capper_tx_cap_exceededThe 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_24houtflow_24h_exceededRetained 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.
leverageleverage_cap_exceededA Hyperliquid leverage update requests a value above maxUpdateLeverage.Lower the requested leverage or make a reviewed policy change before requesting another verdict.
portfolio_leverageleverage_cap_exceededA 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_exposureprotocol_exposure_exceededA 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:

Confirm the rejection

Confirm outcome is rejected and keep the action paused.

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.

Inspect freshness metadata

Inspect dataFreshness.sources[]. source names the feed, status is fresh, cached, or unavailable, asOf is the observation time, and ageMs is its age when Guardian evaluated the action.

Correlate the evidence

Use evidence.sources and redacted evidence.observations when returned to correlate the verdict with the dependency.

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.

Drain and revoke

Use the validated replacement to drain or reconcile existing requests for the same agent owner, then revoke the old key. Request ownership is not tied to the individual credential that created it.

Watch for missed clients

Watch for 401 responses and the old key's last-used metadata to find a client that missed the rotation.

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.

ResponseMeaningBuilder response
401The key is absent, invalid, expired, or revoked.Stop requests and replace or re-authenticate the credential. Do not retry with the same value.
403Authentication 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.

Respond to the cause

Revoke and replace credentials only when compromise is suspected. For data or service incidents, preserve the current key and escalate the named dependency instead.

Resume with a fresh verdict

Resume with a new verification request only after the cause is understood and the exact action is still intended.

See the API reference for the complete verdict shape and HTTP status handling.