Skip to content

Troubleshoot HTTP delivery

Start with the API call’s HTTP status and, if available, the durable data.id. The top-level request_id identifies the API call; data.id identifies the outbound request. Keep both when investigating.

Symptom Meaning and next action
API 202, destination not called yet Work is accepted. Inspect its status, scheduled_at, and latest attempt’s retry.next_attempt_at. delivering includes retry waits.
Timeout, connection lost, or API 500/502/503 Acceptance may be unknown. Retry unchanged input with the original idempotency key within 24 hours. Without a key, inspect before resubmitting because work may already exist.
API 401 Check the server-side project key and bearer header. A revoked key must be replaced. Do not send this key to the receiver.
API 409 Compare the original idempotency input, or inspect lifecycle eligibility for cancel/replay. Do not silently switch to a new key.
API 413 or 422 Check size limits and error.details. Correct the input before retrying. The destination must be public HTTPS.
API 429 with plan_limit_exceeded Workspace allowance is exhausted. Inspect error.details, upgrade, delete an unused schedule if applicable, or wait until resets_at. Tight-loop retries do not restore allowance.
An initial read returns 404 after 202 Allow the query projection a short time to catch up, then retry the read with a bounded wait. Confirm the ID and project. Do not recreate the accepted request.
Persistent read 404 Check for a typo, another project’s key, or terminal history outside the plan’s visibility window. Active work remains visible.

For example, retry a new request’s read every second for up to 30 seconds, then stop and surface the missing-history result for investigation. This is a bounded diagnostic window, not a promised projection deadline. A scheduled request can legitimately remain active much longer.

Inspect response_status_code, error_message, attempt_number, and retry on completed attempts.

Attempt outcome Next action
2xx but business work did not finish Stormedo treats every 2xx as success and does not inspect response bodies. Acknowledge only after durable processing or durable handoff.
3xx Redirects are not followed. Submit the final public HTTPS URL.
400, 401, 403, 404, or other ordinary 4xx Fix payload, destination authentication, route, or permissions. These are terminal unless the status is 408 or 429. Replay only after correcting the cause.
408, 429, or 5xx Retryable while attempts remain. Inspect the recorded next attempt time. Destination Retry-After can extend the wait up to 24 hours.
DNS, connection, or timeout error Verify public DNS, reachability, TLS, and receiver latency. The receiver may have processed a timed-out attempt, so keep duplicate handling in place.
No retry despite a temporary failure Check total attempt budget. Quick send, raw SDK sends, and schedules default to one attempt; advanced JSON requests default to three.
Cancel returned 202 but request succeeded The cancellation signal raced with an in-flight attempt. Cancellation cannot undo a completed business effect.
Replay returns 409 The original is still active. Wait for succeeded, failed, or cancelled, then replay if appropriate.

Reject unverified deliveries before processing. Log the verifier error code and your operation’s outcome, without logging API keys, destination secrets, or the complete signature token.

Verifier code Check
missing_header, duplicated_header, malformed_header Require exactly one Stormedo-Signature and one Stormedo-Request-Id. Inspect proxy header handling.
body_mismatch Capture original bytes before JSON parsing, character decoding, decompression, or re-serialization.
audience_mismatch Use the submitted public URL, including path, query, and trailing slash. Do not use the receiver’s internal proxy URL.
project_mismatch or issuer_mismatch Configure the expected project and production issuer. Do not derive trusted values from token claims.
method_mismatch or request_id_mismatch Pass the received method and single request-ID header. Check middleware rewrites.
token_expired or token_not_yet_valid Synchronize server clocks and verify immediately at ingress. Do not disable time checks.
jwks_unavailable Public-key retrieval failed. Return a temporary failure such as 503; never bypass verification.
unknown_signing_key, invalid_jwks, invalid_signature Confirm the trusted JWKS endpoint and key rotation/cache behavior. Reject the request and investigate.

Use the complete receiver examples to compare middleware order and error handling.

A schedule’s enqueued outcome confirms creation of an occurrence, not completed delivery. Inspect requests with source=recurring and the matching schedule_id.

skipped_usage_limit means no request was created for that occurrence. Restore allowance for future runs. A paused schedule has no next_run_at; resume it to schedule the next future occurrence. Neither outages nor pauses create a catch-up burst. See Schedule recurring requests.