TroubleshootingAn operation expired before signing

An operation expired before signing

Why the window is 30 seconds, what expiry costs, and how to restructure a flow that keeps missing it.

The error

{
  "error": {
    "kind": "invalid_request_error",
    "code": "operation_expired",
    "message": "The authorization expired before it was signed, create a new operation. Authorizations are short-lived because they pin live chain state.",
    "param": null,
    "request_id": "req_..."
  }
}

The operation moves to expired. Nothing moved, no fee was charged, and no signature exists. Creating a replacement is safe.

Why 30 seconds

The authorization pins live chain state. On Solana that is a blockhash with a hard on-chain lifetime: a finalized blockhash is already about 35 slots old when we read it, leaving roughly 46 seconds of its 150-slot life. The message cannot be rebuilt once your key has signed it, so the window has to close well before the blockhash does.

The window is a machine budget, not a human one. Decode, rebuild, one KMS call: well under a second.

Common causes

CauseFix
A human approval step inside the windowMove the approval before POST /operations. Create the operation only once the decision is made
The verifier fetching remote data per sendCache the constants and the wallet's signing_reference at startup. Nothing in the procedure needs a network call except your KMS
A cold-start serverless signerKeep the signing path warm, or run it as a long-lived service
A queue between create and signCreate the operation from the worker that will sign it, not from an upstream producer
A slow KMS regionCo-locate the signing service with the key

The shape that works

1. Your product decides a send should happen.
2. Any human approval happens here.
3. Worker: POST /operations
4. Same worker, same request: verify, sign, POST /authorize
5. Wait for wallet.operation_confirmed

Steps 3 and 4 belong in one synchronous block. If they can be separated by a queue, a retry, or a deploy, the window will be missed eventually.

If it keeps happening

Instrument the elapsed time between your POST /operations response and your POST /authorize request. If the median is above a second, the problem is in your pipeline rather than in the window. Expired operations cost nothing, so a retry loop that recreates and re-signs is a legitimate stopgap while you restructure.

See Sending Funds and the Signing Guide.