openclaw - 💡(How to fix) Fix openai-codex provider: multi-turn sessions permanently break with 400 invalid_encrypted_content after an OAuth token refresh

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

When the agent model is openai-codex/gpt-5.5 authenticated via a ChatGPT-plan OAuth profile, any multi-turn session works for a while and then every subsequent turn fails silently with HTTP 400 invalid_encrypted_content from the Codex Responses API.

The failure is deterministically triggered by an OAuth access-token refresh. OpenClaw replays encrypted_content reasoning items from earlier turns; those blobs are bound to the access token that produced them, so once the token is refreshed (periodic refresh, or re-auth on gateway restart) the Codex backend can no longer decrypt them and rejects the whole request.

The user receives no reply at all — the run ends as an empty non_deliverable_terminal_turn.

Error Message

[openai-transport] WARN [responses] error provider=openai-codex api=openai-codex-responses model=gpt-5.5 name=Error status=400 code=invalid_encrypted_content type=invalid_request_error message=400 The encrypted content gAAA...= could not be verified. Reason: Encrypted content could not be decrypted or parsed. [agent/embedded] WARN embedded run agent end [agent/embedded] WARN embedded run failover decision [diagnostic] ERROR lane task error: lane=main durationMs=2505 error="FailoverError: LLM request failed: provider rejected the request schema or tool payload." [model-fallback/decision] WARN model fallback decision ERROR Embedded agent failed before reply: LLM request failed: provider rejected the request schema or tool payload.

Root Cause

Trivial sessions (e.g. heartbeat) keep working because they don't replay accumulated reasoning items.

Code Example

[openai-transport] WARN  [responses] error provider=openai-codex api=openai-codex-responses
  model=gpt-5.5 name=Error status=400 code=invalid_encrypted_content type=invalid_request_error
  message=400 The encrypted content gAAA...= could not be verified.
  Reason: Encrypted content could not be decrypted or parsed.
[agent/embedded] WARN  embedded run agent end
[agent/embedded] WARN  embedded run failover decision
[diagnostic] ERROR lane task error: lane=main durationMs=2505
  error="FailoverError: LLM request failed: provider rejected the request schema or tool payload."
[model-fallback/decision] WARN model fallback decision
ERROR Embedded agent failed before reply: LLM request failed: provider rejected the request schema or tool payload.

---

{ "type": "model.completed",
  "data": { "terminalError": "non_deliverable_terminal_turn",
            "assistantTexts": [],
            "promptCache": { "lastCallUsage": { "input": 0, "output": 0, "total": 0 } } } }
{ "type": "session.ended", "data": { "status": "error",
            "terminalError": "non_deliverable_terminal_turn" } }
RAW_BUFFERClick to expand / collapse

openai-codex provider: multi-turn sessions permanently break with 400 invalid_encrypted_content after an OAuth token refresh

Summary

When the agent model is openai-codex/gpt-5.5 authenticated via a ChatGPT-plan OAuth profile, any multi-turn session works for a while and then every subsequent turn fails silently with HTTP 400 invalid_encrypted_content from the Codex Responses API.

The failure is deterministically triggered by an OAuth access-token refresh. OpenClaw replays encrypted_content reasoning items from earlier turns; those blobs are bound to the access token that produced them, so once the token is refreshed (periodic refresh, or re-auth on gateway restart) the Codex backend can no longer decrypt them and rejects the whole request.

The user receives no reply at all — the run ends as an empty non_deliverable_terminal_turn.

Environment

  • OpenClaw 2026.5.18 (build 50a2481, trace gitSha 39ee0dd)
  • macOS 26.2 (arm64), Node v25.9.0
  • Provider openai-codex, model gpt-5.5, api openai-codex-responses, harness pi
  • Auth: ChatGPT-plan OAuth (auth_mode=chatgpt, plan pro)
  • Gateway mode local

Steps to reproduce

  1. Configure an agent with model.primary = openai-codex/gpt-5.5 using a ChatGPT-plan OAuth auth profile.
  2. Start a fresh session and send several turns that involve tool calls (so reasoning items accumulate in history). They succeed.
  3. Wait for the openai-codex OAuth access token to be refreshed — happens periodically, and on every gateway restart (resolving authentication…). The refresh rewrites ~/.openclaw/agents/<id>/agent/auth-profiles.json + auth-state.json.
  4. Send another turn in the same session.

Expected

The turn completes normally. A token refresh should not invalidate an in-flight conversation.

Actual

Every turn after the refresh fails:

[openai-transport] WARN  [responses] error provider=openai-codex api=openai-codex-responses
  model=gpt-5.5 name=Error status=400 code=invalid_encrypted_content type=invalid_request_error
  message=400 The encrypted content gAAA...= could not be verified.
  Reason: Encrypted content could not be decrypted or parsed.
[agent/embedded] WARN  embedded run agent end
[agent/embedded] WARN  embedded run failover decision
[diagnostic] ERROR lane task error: lane=main durationMs=2505
  error="FailoverError: LLM request failed: provider rejected the request schema or tool payload."
[model-fallback/decision] WARN model fallback decision
ERROR Embedded agent failed before reply: LLM request failed: provider rejected the request schema or tool payload.

Run trajectory for the failed run:

{ "type": "model.completed",
  "data": { "terminalError": "non_deliverable_terminal_turn",
            "assistantTexts": [],
            "promptCache": { "lastCallUsage": { "input": 0, "output": 0, "total": 0 } } } }
{ "type": "session.ended", "data": { "status": "error",
            "terminalError": "non_deliverable_terminal_turn" } }

The session stores "[assistant turn failed before producing content]" (or an empty assistant message) and the user gets nothing back.

Evidence — refresh correlates exactly with the breakage

Session e4a909f8:

Time (KST)EventResult
17:05 / 17:10 / 17:12 / 17:154 turnssuccess
17:19:25auth-profiles.json + auth-state.json rewritten (token refresh)
17:20:23next turn400 invalid_encrypted_content

Session bf79fe90:

Time (KST)EventResult
16:09first turnsuccess
16:29:56gateway restart → resolving authentication… (token re-issued)
16:33 / 16:38 / 17:03 / 17:04every turn400 invalid_encrypted_content

Trivial sessions (e.g. heartbeat) keep working because they don't replay accumulated reasoning items.

Root cause (two distinct issues)

1. Stale encrypted_content reasoning replay. For openai-codex-responses, OpenClaw replays encrypted_content reasoning items from prior turns. These blobs are cryptographically bound to the OAuth access token that generated them. After a token refresh, all previously-stored encrypted_content is undecryptable, but OpenClaw keeps sending it.

Note: requiresReasoningContentReplay("gpt-5.5") returns false (gpt-5.5 is not in REASONING_CONTENT_REPLAY_MODEL_IDS = kimi-* / mimo-* / deepseek-v4-*), so the transcript policy resolves dropReasoningFromHistory: true. Despite that, the outgoing request still contains stale encrypted_content and is rejected — so either the codex provider path bypasses the dropReasoningFromHistory transcript policy, or dropReasoningFromHistory / shouldPreserveCurrentToolTurnReasoning does not strip encrypted_content thoroughly enough. Maintainers should verify which.

2. No recovery on invalid_encrypted_content. The 400 code=invalid_encrypted_content is classified as FailoverError: provider rejected the request schema or tool payload and routed to model-fallback. With no fallback model configured, the run hard-fails with zero output. invalid_encrypted_content is a recoverable, well-known Codex error and should not be treated as a schema/tool-payload rejection.

Suggested fix

  • On 400 code=invalid_encrypted_content: retry once on the same model after stripping all encrypted_content from reasoning items in the request. Do not route to model fallback.
  • And/or: tag stored reasoning items with the credential/token id that produced them; when the active openai-codex token changes, drop reasoning items whose token id no longer matches before building the request.
  • And/or: drop/invalidate stored encrypted_content for affected sessions whenever the openai-codex OAuth token is refreshed.

Impact

Any multi-turn openai-codex (ChatGPT-plan OAuth) session becomes permanently unusable after the first token refresh — which happens roughly hourly and on every gateway restart. The user gets a completely silent failure (empty turn, no error surfaced to the channel).

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix openai-codex provider: multi-turn sessions permanently break with 400 invalid_encrypted_content after an OAuth token refresh