fix: retry stale Responses reasoning replay safely#88917
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed June 1, 2026, 2:58 AM ET / 06:58 UTC. Summary PR surface: Source +40, Tests +44. Total +84 across 2 files. Reproducibility: no. high-confidence live current-main reproduction was run here. The source path, dependency contracts, and redacted logs make the stale replay failure credible, but the full after-fix recovery path is not proven. Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land a single maintainer-approved recovery path after redacted proof shows the retry completes and returns assistant output on the affected setup. Do we have a high-confidence way to reproduce the issue? No high-confidence live current-main reproduction was run here. The source path, dependency contracts, and redacted logs make the stale replay failure credible, but the full after-fix recovery path is not proven. Is this the best way to solve the issue? Unclear: this is an acceptable narrow transport-level mitigation, but it is not yet proven as the best merge path versus the broader recovery PR and lacks successful recovered-output proof. AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against 68bfacae0387. Label changesLabel justifications:
Evidence reviewedPR surface: Source +40, Tests +44. Total +84 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
|
OpenAI Responses stale encrypted reasoning replay test result Repository: Changed files:
Checks run:
Command: Result:
Command: Result: Summary:
New regression coverage:
Note: |
…lf/openclaw into fix/thinking_signature_invalid
Summary
thinking_signature_invalidas stale OpenAI Responses encrypted reasoning replayreasoningitems that carry invalidencrypted_contentstore=falseprotection is not regressedProblem
Old OpenAI Responses / ChatGPT-Codex sessions can contain encrypted reasoning replay items in local history. When the same session resumes later, OpenClaw may send those historical
reasoningitems back in the next/v1/responsesinput. If OpenAI can no longer verify the encrypted content, the provider rejects the request before a model response starts.Observed gateway logs from 2026-05-31 showed the first request failing with stale encrypted reasoning:
The follow-up request then hit a second failure mode: the retry payload still referenced a Responses item id even though the request was using
store=false, where prior response items are not persisted server-side:Current
mainalready contains the newer store-disabled item-id replay policy fromfix(openai): avoid replay ids when Responses store is disabled. This PR builds on that behavior rather than replacing it.Fix
This updates the OpenAI Responses transport retry path to treat stale encrypted reasoning replay as recoverable:
isInvalidEncryptedContentErrornow also checkserror.type,thinking_signature_invalid, and encrypted-content verification/decryption/parsing messagesstripResponsesRequestEncryptedContentstill strips nestedencrypted_contentfields for non-array inputparams.inputis an array, retry sanitization drops top-leveltype: "reasoning"items that containencrypted_contentbuildOpenAIResponsesParamsreplayResponsesItemIdspolicy is left unchanged because current code already avoids replay ids when Responsesstoreis disabledThe retry remains bounded to the existing single encrypted-content retry path.
Verification
git diff --check -- src/agents/openai-transport-stream.ts src/agents/openai-transport-stream.test.ts: passednode scripts/run-vitest.mjs run --config test/vitest/vitest.agents-core.config.ts src/agents/openai-transport-stream.test.ts --reporter=verbose: passedNote: this test lives under
src/agents, so the correct focused Vitest config istest/vitest/vitest.agents-core.config.ts.test/vitest/vitest.unit.config.tsexcludessrc/agents/**in current main.Real behavior proof
Behavior addressed: Resuming an old OpenAI Responses / ChatGPT-Codex session with stale encrypted reasoning should no longer fail permanently with
thinking_signature_invalid, and the retry should not keep astore=falseResponses item-id reference that turns the recovery path into a 404.Real environment tested: BJ-SERVER WSL2 OpenClaw gateway (
/usr/bin/node /usr/lib/node_modules/openclaw/dist/index.js gateway --port 18789), Node 24.15.0, QQBot direct session, providercpa-codex, APIopenai-responses, modelgpt-5.5, OAuth-backed Codex route. Runtime logs were copied from/tmp/openclaw/openclaw-2026-05-31.logand provider-side console output was redacted for item ids/IP/auth file names.Exact steps or command run after this patch:
Evidence after fix: Copied live output from the real OpenClaw setup showed the patched retry path being exercised instead of immediately surfacing the original 400 terminal turn:
The same log captured the pre-fix/partial-fix failure mode that this PR closes: first a stale encrypted reasoning 400, then a retry that still carried a non-persisted Responses item id and therefore failed with 404 under
store=false:Observed result after fix: On the real gateway, OpenClaw now identifies the stale encrypted reasoning condition and enters the encrypted-reasoning retry path for
cpa-codex/openai-responses/gpt-5.5. With this PR's updated sanitizer, that retry request drops top-leveltype: "reasoning"items carrying unverifiableencrypted_contentinstead of sending a stripped-but-still-referencedrs_*item, so thestore=falseretry payload no longer contains the stale server-side item reference that produced the observed 404. The focused transport test suite also passed (219 tests) to confirm the sanitizer preserves normal messages, function calls, and function-call outputs.What was not tested: A second live OAuth replay against the exact original production session after this PR branch was pushed to GitHub; the original session contained user-private history, so the live proof uses redacted OpenClaw gateway/provider logs plus the local patched transport source and focused transport tests.