Skip to content
Tollgate Docs

Troubleshooting

Always receiving 402

  • Confirm x-tollgate-iou is set on the retry, not the initial request.
  • Ensure the header value is base64-encoded JSON, not raw JSON. Use encodeIOUHeader() from @tollgatepay/core/eip712.
  • Check the JSON envelope has version: "iou-v1".

INVALID_SIGNATURE

The recovered signer didn't match agentAddress. Likely causes:

  • Domain drift. The 402 eip712Domain must be echoedexactly into the typed-data signing call. A single changed byte in verifyingContract or salt moves the digest.
  • Message-field drift. Every uint256 must sign as bigint. A stringly-typed chainId in the message (not the envelope) produces a different digest.
  • Signer mismatch. Your signing key's address is not agentAddress.

NONCE_REUSED

Agents race on the same (agent, developer, path) tuple (two concurrent requests pick the same prev+1). Mitigate:

  • Serialize request issuance per tuple in your agent code, or
  • Use StoreBackedNonceStore(redisStore) with a CAS- capable backend. The default in-memory store is single-process only.

EXPIRED_IOU

Deadline window is 120s. Common causes:

  • Clock drift on the agent host. Run NTP.
  • Time between signing and server-hit > 60s (e.g. queued retries). Re-sign rather than reuse.

PATH_APPEARS_DYNAMIC

Your route has a dynamic segment (e.g. /api/users/:id) and the canonicalizer conservatively rejects it. Fix by passing endpointTemplate: "/api/users/[id]" to wrap().

FACILITATOR_UNAVAILABLE (503)

The middleware couldn't reach the facilitator. Quick fixes:

  • Retry with exponential backoff; facilitator blips are usually <30s.
  • Set onFacilitatorError: "serve-untracked" to accept the IOU locally without recording it. Trades auditability for availability — only appropriate for low-value routes.

Enable verbose logs

import { createLogger } from "@tollgatepay/core/observability";
import { initTollgate } from "@tollgatepay/next";

export const { wrap } = initTollgate({
  apiKey: process.env.TOLLGATE_API_KEY!,
  payoutAddress: "0x...",
  developerSalt: "0x...",
  logger: createLogger({ service: "tollgate-edge", level: "debug" }),
});