Skip to content

fix: persist and replay original status code in idempotency layer#10

Open
tmchow wants to merge 1 commit intoEveryInc:mainfrom
tmchow:fix/idempotency-status-code
Open

fix: persist and replay original status code in idempotency layer#10
tmchow wants to merge 1 commit intoEveryInc:mainfrom
tmchow:fix/idempotency-status-code

Conversation

@tmchow
Copy link

@tmchow tmchow commented Mar 12, 2026

Bug

The idempotency layer had a status_code column in the DB and an options.statusCode parameter in storeIdempotencyResult(), but the wiring was never completed:

Location Problem
storeIdempotentMutationResult() Called storeIdempotencyResult without passing statusCode
getStoredIdempotencyRecord() Never read status_code from the DB
maybeReplayIdempotentMutation() Hardcoded 200 in the replay response

Result: every idempotency replay returned 200 regardless of the original status — e.g. a 201 Created became 200 OK on retry.

Fix

Threaded status_code through all three layers in server/db.ts and server/agent-routes.ts:

// storeIdempotentMutationResult — pass status through
storeIdempotencyResult(slug, routeKey, replay.idempotencyKey, body, replay.requestHash, { statusCode: status })

// getStoredIdempotencyRecord — read it back
SELECT response_json, request_hash, status_code FROM mutation_idempotency ...
return { response, requestHash, statusCode }

// maybeReplayIdempotentMutation — use stored value, fallback to 200 for legacy rows
sendMutationResponse(res, stored.statusCode ?? 200, stored.response)

Legacy rows without status_code fall back to 200 (the column defaults to 200 per the existing migration).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant