Skip to content

fix: retry stale Responses reasoning replay safely#88917

Closed
physicswolf wants to merge 8 commits into
openclaw:mainfrom
physicswolf:fix/thinking_signature_invalid
Closed

fix: retry stale Responses reasoning replay safely#88917
physicswolf wants to merge 8 commits into
openclaw:mainfrom
physicswolf:fix/thinking_signature_invalid

Conversation

@physicswolf

@physicswolf physicswolf commented Jun 1, 2026

Copy link
Copy Markdown

Summary

  • recognize thinking_signature_invalid as stale OpenAI Responses encrypted reasoning replay
  • retry once without replayed top-level reasoning items that carry invalid encrypted_content
  • keep the existing store-disabled item-id replay policy intact, so current store=false protection is not regressed

Problem

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 reasoning items back in the next /v1/responses input. 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:

[2026-05-31 16:23:41] [request:12a4ddcf] request error, status=400,
message="The encrypted content for item rs_<redacted> could not be verified.
Reason: Encrypted content could not be decrypted or parsed."
POST "/v1/responses" from <redacted-ip>

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:

[2026-05-31 16:23:42] [request:7ad13c95] request error, status=404,
message="Item with id 'rs_<redacted>' not found. Items are not persisted when `store` is set to false.
Try again with `store` set to true, or remove this item from your input."
POST "/v1/responses" from <redacted-ip>

Current main already contains the newer store-disabled item-id replay policy from fix(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:

  • isInvalidEncryptedContentError now also checks error.type, thinking_signature_invalid, and encrypted-content verification/decryption/parsing messages
  • stripResponsesRequestEncryptedContent still strips nested encrypted_content fields for non-array input
  • when params.input is an array, retry sanitization drops top-level type: "reasoning" items that contain encrypted_content
  • other input items keep the existing recursive encrypted-content stripping behavior
  • the existing buildOpenAIResponsesParams replayResponsesItemIds policy is left unchanged because current code already avoids replay ids when Responses store is disabled

The 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: passed
  • node scripts/run-vitest.mjs run --config test/vitest/vitest.agents-core.config.ts src/agents/openai-transport-stream.test.ts --reporter=verbose: passed
    • Test Files: 1 passed
    • Tests: 219 passed

Note: this test lives under src/agents, so the correct focused Vitest config is test/vitest/vitest.agents-core.config.ts. test/vitest/vitest.unit.config.ts excludes src/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 a store=false Responses 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, provider cpa-codex, API openai-responses, model gpt-5.5, OAuth-backed Codex route. Runtime logs were copied from /tmp/openclaw/openclaw-2026-05-31.log and provider-side console output was redacted for item ids/IP/auth file names.

Exact steps or command run after this patch:

grep -n "retrying without encrypted reasoning content\|thinking_signature_invalid\|Items are not persisted when `store` is set to false" /tmp/openclaw/openclaw-2026-05-31.log | tail -40

grep -n "record.type === \"reasoning\" && \"encrypted_content\" in record\|thinking_signature_invalid\|replayResponsesItemIds: payloadPolicy.explicitStore" src/agents/openai-transport-stream.ts

node --experimental-strip-types --check src/agents/openai-transport-stream.ts

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:

/tmp/openclaw/openclaw-2026-05-31.log:1600:{"time":"2026-05-31T16:23:41.007+08:00","hostname":"BJ-SERVER","message":"[responses] retrying without encrypted reasoning content provider=cpa-codex api=openai-responses model=gpt-5.5"}
/tmp/openclaw/openclaw-2026-05-31.log:1615:{"time":"2026-05-31T16:24:54.160+08:00","hostname":"BJ-SERVER","message":"[responses] retrying without encrypted reasoning content provider=cpa-codex api=openai-responses model=gpt-5.5"}
/tmp/openclaw/openclaw-2026-05-31.log:1781:{"time":"2026-05-31T16:31:29.836+08:00","hostname":"BJ-SERVER","message":"[responses] retrying without encrypted reasoning content provider=cpa-codex api=openai-responses model=gpt-5.5"}
/tmp/openclaw/openclaw-2026-05-31.log:1853:{"time":"2026-05-31T16:49:27.258+08:00","hostname":"BJ-SERVER","message":"[responses] retrying without encrypted reasoning content provider=cpa-codex api=openai-responses model=gpt-5.5"}
/tmp/openclaw/openclaw-2026-05-31.log:2110:{"time":"2026-05-31T17:21:26.187+08:00","hostname":"BJ-SERVER","message":"[responses] retrying without encrypted reasoning content provider=cpa-codex api=openai-responses model=gpt-5.5"}
/tmp/openclaw/openclaw-2026-05-31.log:2122:{"time":"2026-05-31T17:23:51.253+08:00","hostname":"BJ-SERVER","message":"[responses] retrying without encrypted reasoning content provider=cpa-codex api=openai-responses model=gpt-5.5"}

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:

[2026-05-31 16:23:41] request error, error status: 400, error message: The encrypted content for item rs_<redacted> could not be verified. Reason: Encrypted content could not be decrypted or parsed.
[2026-05-31 16:23:42] request error, error status: 404, error message: Item with id 'rs_<redacted>' not found. Items are not persisted when `store` is set to false. Try again with `store` set to true, or remove this item from your input.

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-level type: "reasoning" items carrying unverifiable encrypted_content instead of sending a stripped-but-still-referenced rs_* item, so the store=false retry 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.

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: S triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels Jun 1, 2026
@clawsweeper

clawsweeper Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed June 1, 2026, 2:58 AM ET / 06:58 UTC.

Summary
The PR broadens OpenAI Responses stale encrypted-reasoning error detection, drops top-level encrypted reasoning items on retry, and adds focused transport regression tests.

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: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🐚 platinum hermit
Result: blocked until stronger real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

Proof guidance:

  • [P1] Needs stronger real behavior proof before merge: Redacted logs show the retry path was reached, but they do not show a successful after-fix provider retry, sanitized retry payload, or recovered assistant output. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] The supplied real-environment proof shows retry log entries but not a successful recovered assistant response or sanitized retry payload after this patch.
  • [P1] The retry path changes which persisted Responses reasoning items survive recovery, so this remains session-state-sensitive until successful recovery proof is added.
  • [P1] A broader open recovery PR targets the same root problem, so maintainers should choose the canonical recovery shape before merging parallel fixes.

Maintainer options:

  1. Require recovered-output proof (recommended)
    Ask for redacted terminal output, logs, or an artifact showing the patched retry payload succeeds and produces assistant output.
  2. Defer to the broader recovery PR
    Pause this narrow PR if maintainers prefer the wrapper-level recovery approach in fix(agents): recover invalid OpenAI Responses reasoning replay #84267 as the canonical fix.
  3. Accept the narrow mitigation risk
    Maintainers can intentionally merge the sanitizer based on code review and focused tests while owning the remaining live-recovery uncertainty.

Next step before merge

  • [P1] The remaining blocker is contributor-supplied recovery proof plus maintainer selection of the canonical session-recovery path, not a safe automated code repair.

Security
Cleared: The diff only changes OpenAI Responses retry sanitization and focused tests; it does not touch dependencies, lockfiles, CI, secrets, permissions, install scripts, or package execution paths.

Review details

Best 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 changes

Label justifications:

  • P1: The PR targets OpenAI Responses continuation failures that can block real agent/channel turns after stale reasoning replay.
  • merge-risk: 🚨 session-state: The diff changes retry-time handling of persisted Responses reasoning items and can affect resumed conversation state.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: Redacted logs show the retry path was reached, but they do not show a successful after-fix provider retry, sanitized retry payload, or recovered assistant output. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source +40, Tests +44. Total +84 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 48 8 +40
Tests 1 55 11 +44
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 103 19 +84

What I checked:

  • Repository policy read and applied: Root and scoped agent policy require dependency/Codex source inspection and session-state-sensitive review for agent runtime changes. (AGENTS.md:8, 68bfacae0387)
  • Current main retry classifier is narrower: Current main only recognizes invalid_encrypted_content and does not classify thinking_signature_invalid as recoverable. (src/agents/openai-transport-stream.ts:771, 68bfacae0387)
  • Current main store-disabled policy is separate: Current main resolves the Responses payload policy with storeMode disable and derives replayResponsesItemIds from explicitStore, so the PR is not replacing that policy. (src/agents/openai-transport-stream.ts:2095, 68bfacae0387)
  • PR head changes the retry sanitizer: The PR head recognizes thinking_signature_invalid and encrypted-content verification/decryption/parsing messages, then drops top-level reasoning items carrying encrypted_content from array input. (src/agents/openai-transport-stream.ts:771, 22aa9583be3d)
  • PR head adds focused regression coverage: The added tests cover the new error classifier and the retry payload shape that removes encrypted reasoning while preserving messages and tool items. (src/agents/openai-transport-stream.test.ts:3469, 22aa9583be3d)
  • OpenAI SDK error contract supports top-level code/type/message checks: The openai-node 6.39.1 APIError exposes code, type, and an Error.message built from the response error body. (openai-node/src/core/error.ts:20)

Likely related people:

  • steipete: Recent current-main work modified the same OpenAI transport stream and tests in the agent runtime area. (role: recent area contributor; confidence: high; commits: b23ace1d04ca; files: src/agents/openai-transport-stream.ts, src/agents/openai-transport-stream.test.ts)
  • zhanghang02: Authored the current-main store-disabled Responses replay-id policy that this PR explicitly preserves. (role: recent replay-policy contributor; confidence: high; commits: 03dec8bb3a00; files: src/agents/openai-transport-stream.ts, src/agents/openai-transport-stream.test.ts)
  • vincentkoc: Current blame around the retry classifier and sanitizer points to a recent large refactor of the same transport files. (role: recent area contributor; confidence: medium; commits: dc9e67d2d472; files: src/agents/openai-transport-stream.ts, src/agents/openai-transport-stream.test.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. labels Jun 1, 2026
@physicswolf

Copy link
Copy Markdown
Author

OpenAI Responses stale encrypted reasoning replay test result

Repository:
D:\Document\Workspace\Coding\openclaw

Changed files:

  • src/agents/openai-transport-stream.ts
  • src/agents/openai-transport-stream.test.ts

Checks run:

  1. Whitespace / patch sanity

Command:
git diff --check -- src/agents/openai-transport-stream.ts src/agents/openai-transport-stream.test.ts

Result:
passed

  1. Focused agents-core Vitest regression suite

Command:
node scripts/run-vitest.mjs run --config test/vitest/vitest.agents-core.config.ts src/agents/openai-transport-stream.test.ts --reporter=verbose

Result:
passed

Summary:

  • Test Files: 1 passed
  • Tests: 219 passed
  • Duration: 21.71s

New regression coverage:

  • recognizes thinking_signature_invalid and encrypted-content verification/decryption/parsing messages as stale encrypted reasoning replay errors
  • drops top-level type: "reasoning" items carrying encrypted_content before the retry request is sent
  • preserves non-reasoning input items, including messages, function calls, and function-call outputs, while recursively stripping nested encrypted_content

Note:
This test file belongs to src/agents, so the correct focused config is test/vitest/vitest.agents-core.config.ts. The current test/vitest/vitest.unit.config.ts excludes src/agents/**, which is why it reports "No test files found" for this file.

@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels Jun 1, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P1 High-priority user-facing bug, regression, or broken workflow. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: S status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant