Skip to content

Errors & retries ​

Handle failures according to the operation. A failed or timed-out write may already have committed; a lost response is not proof that nothing changed.

Read an SDK error ​

FunnelSdkHttpError, exported by @funnelsgrove/runtime, exposes:

FieldMeaning
statusCodeHTTP response status.
messageHuman-readable error.
codeOperation-specific or shared error code, when provided.
retryableExplicit server boolean, or null when unknown.
retryAfterRaw Retry-After header, or null when unavailable.
checkoutRequestIdCheckout diagnostic ID, when provided.

Network failures remain ordinary fetch errors. An absent code or retry hint on an older API is unknown, not a parsing failure. An explicit retryable: false prevents automatic replay; null does not grant permission to retry a write.

Request budgets ​

Current runtime user and upload operations accept an optional AbortSignal. Caller cancellation rejects with AbortError (or the supplied abort reason); an exhausted budget rejects with TimeoutError.

OperationClient budgetReplay policy
User reads and mutations25 seconds total, including the response body and retry delayOperation-specific; see below.
Photo preparation25 secondsOne attempt.
Direct photo upload60 seconds after preparationOne attempt.
Legacy base64 upload25 secondsOne attempt.
Runtime configuration25 seconds shared across coalesced readersUp to three attempts within that budget.

Cancellation and budget exhaustion are never automatically replayed. Payment operations have their own attempt and recovery rules; do not apply the user-read retry policy to checkout.

When the runtime retries ​

getCurrentUser and the compatibility getUserSubscriptionStatus method may replay once after a network failure or HTTP 408, 429, 500, 502, 503, or 504, unless the response says retryable: false.

bootstrapUser uses that policy only with a nonempty idempotencyKey. A replay reuses the original serialized request body and key. Other user mutations execute once.

For an eligible replay, Retry-After seconds or an HTTP date sets the delay. Without a usable header, the delay is 250 ms. If that delay exceeds the remaining budget, the runtime returns the failure rather than retrying early.

Common responses ​

Status or codeMeaning and next step
400, SDK_INVALID_REQUESTCorrect the request before retrying.
401, SDK_UNAUTHORIZEDCheck the project key or operation's identity proof.
403, SDK_FORBIDDENThe requested scope or origin is not permitted.
404, SDK_NOT_FOUNDCheck the resource and project scope.
409, SDK_CONFLICTResolve the conflicting state; read the operation's contract.
409, SDK_CONCURRENT_UPDATERetry the same logical request after Retry-After: 1.
413, SDK_PAYLOAD_TOO_LARGEReduce the payload.
415, SDK_UNSUPPORTED_MEDIA_TYPEUse a supported content type.
429Wait for Retry-After; only replay operations that permit it.
503, SDK_DEPENDENCY_UNAVAILABLEFollow retryable and the operation-specific rules below.

Operation-specific codes take precedence over shared codes. Older responses may contain only error. Do not treat an unfamiliar code or a server failure as proof of an inactive subscription or an unsuccessful payment.

Identity operations ​

Bootstrap: a transient scope-read failure may be retried once by the server before any write begins. If it still fails, the response is 503, SDK_DEPENDENCY_UNAVAILABLE, retryable: true, with Retry-After: 1. Failures after writing are subject to the operation's existing idempotency rules.

User updates and email capture: dependency failures after entering the write path are non-retryable. Earlier identity, consent, or event writes may have committed. Cancellation does not roll them back.

Subscription verification: a transient read failure can return retryable 503 after a bounded internal retry. Preserve the error state; it does not mean that access is inactive.

App Login: a dependency failure before the registration workflow can return retryable 503. After entering the workflow, a classified dependency failure has retryable: false without Retry-After. Registration may already exist. A later explicit login reuses the original registration identity and timestamp.

Checkout diagnostics ​

Checkout creation can return 401 with code: "checkout_identity_owner_unavailable" and a server-generated UUID checkoutRequestId. The safe message is Checkout identity owner is unavailable.

Keep the ID for support correlation. It is a lookup hint, not an ownership proof or permission to retry a purchase. Never log identity/access tokens, payment credentials, or customer data alongside it.

The runtime preserves this ID in FunnelSdkHttpError; current shared payments forward it in checkout failure telemetry. Older clients can omit it. See Payments for recovery by operation.

Proxies and headers ​

  • The runtime sends X-FunnelsGrove-Runtime-Version for diagnostics. It is optional and never authorizes a request. Signed storage uploads omit it.
  • Runtime-config requests may send Cache-Control: no-cache. If you proxy the API, preserve the required CORS request headers and expose Retry-After.
  • Treat a missing checkoutRequestId, error code or retry hint as unknown rather than as a success.

Build. Launch. Grow.