openclaw - ✅(Solved) Fix openai-codex provider sends empty input[] when context has only systemPrompt → ChatGPT 400 [1 pull requests, 1 comments, 2 participants]

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…
GitHub stats
openclaw/openclaw#73820Fetched 2026-04-29 06:14:39
View on GitHub
Comments
1
Participants
2
Timeline
6
Reactions
0
Timeline (top)
cross-referenced ×2subscribed ×2commented ×1referenced ×1

When the openai-codex provider (api openai-codex-responses, baseUrl https://chatgpt.com/backend-api/codex) is invoked with a context whose messages array is empty but whose systemPrompt is set, the resulting request body contains input: []. ChatGPT's codex backend rejects this with a 400:

One of "input" or "previous_response_id" or 'prompt' or 'conversation_id' must be provided.

In practice the 400 closes the upstream socket before the streaming consumer classifies the failure, so most calls surface to the user as a 15–31s timeout rather than the underlying error — making this hard to diagnose from logs alone. We caught the rawError on one occurrence:

[agent/embedded] embedded run agent end: ... isError=true model=gpt-5.5
  provider=openai-codex
  error=One of "input" or "previous_response_id" or 'prompt' or 'conversation_id' must be provided.
  rawError=One of "input" or "previous_response_id" or 'prompt' or 'conversation_id' must be provided.

with 27 sibling entries from the same workload showing decision=surface_error reason=timeout from=openai-codex/gpt-5.5 for what appears to be the same root cause.

Error Message

timeout rather than the underlying error — making this hard to diagnose error=One of "input" or "previous_response_id" or 'prompt' or 'conversation_id' must be provided. error but doesn't restore functionality for the (legitimate) bootstrap case.

Root Cause

with 27 sibling entries from the same workload showing decision=surface_error reason=timeout from=openai-codex/gpt-5.5 for what appears to be the same root cause.

Fix Action

Workaround

Point active-memory's activeProvider/activeModel at any non-codex provider (e.g. an lmstudio-served model). Confirms codex is the isolated failure point.

PR fix notes

PR #73930: fix(agents): fail fast when openai-codex Responses receives empty messages (#73820)

Description (problem / solution / changelog)

Fixes #73820.

Problem

`buildOpenAIResponsesParams` routes `openai-codex-responses` requests via top-level `instructions` (from `systemPrompt`) and assigns the converted messages array directly to `input`. With `context.messages: []` the resulting `input: []` reaches the Codex backend, which rejects it with:

One of "input" or "previous_response_id" or 'prompt' or 'conversation_id' must be provided.

That 400 closes the upstream socket before the streaming consumer classifies the failure, so callers see a 15-31s timeout instead of the underlying error. Reproduced in the wild via `active-memory`'s memory-flush bootstrap run (#73820, woodhouse-bot reporter).

Fix

Throw a local error before the request is sent when `isCodexResponses && messages.length === 0`, surfacing the actionable `must be provided` text immediately. Non-Codex Responses providers still allow empty `input[]` so the OpenAI Responses path is unchanged.

What changed

FileChange
`src/agents/openai-transport-stream.ts`6-line guard right after `convertResponsesMessages`
`src/agents/openai-transport-stream.test.ts`3 new regression tests + 1 minor test update
`CHANGELOG.md`Unreleased Fixes line

Tests

3 new regression tests:

  1. Throws when `isCodexResponses && messages: []` — exact error message via regex
  2. Does not throw when `isCodexResponses && messages: [user "ping"]` — happy path
  3. Does not throw when `non-codex && messages: []` — preserves OpenAI Responses contract

Plus 1 test fixup: pre-existing `"maps low reasoning to medium for Codex mini"` test had `messages: []`; now passes a single user "ping" to exercise reasoning-effort path without colliding with the new fail-fast.

``` pnpm vitest run src/agents/openai-transport-stream.test.ts → 93 passed (90 existing + 3 new, no regressions, +1 test fixup) ```

🦞 lobster-biscuit


Sign-Off: hclsys

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/agents/openai-transport-stream.test.ts (modified, +85/-1)
  • src/agents/openai-transport-stream.ts (modified, +15/-0)

Code Example

[agent/embedded] embedded run agent end: ... isError=true model=gpt-5.5
  provider=openai-codex
  error=One of "input" or "previous_response_id" or 'prompt' or 'conversation_id' must be provided.
  rawError=One of "input" or "previous_response_id" or 'prompt' or 'conversation_id' must be provided.
RAW_BUFFERClick to expand / collapse

Summary

When the openai-codex provider (api openai-codex-responses, baseUrl https://chatgpt.com/backend-api/codex) is invoked with a context whose messages array is empty but whose systemPrompt is set, the resulting request body contains input: []. ChatGPT's codex backend rejects this with a 400:

One of "input" or "previous_response_id" or 'prompt' or 'conversation_id' must be provided.

In practice the 400 closes the upstream socket before the streaming consumer classifies the failure, so most calls surface to the user as a 15–31s timeout rather than the underlying error — making this hard to diagnose from logs alone. We caught the rawError on one occurrence:

[agent/embedded] embedded run agent end: ... isError=true model=gpt-5.5
  provider=openai-codex
  error=One of "input" or "previous_response_id" or 'prompt' or 'conversation_id' must be provided.
  rawError=One of "input" or "previous_response_id" or 'prompt' or 'conversation_id' must be provided.

with 27 sibling entries from the same workload showing decision=surface_error reason=timeout from=openai-codex/gpt-5.5 for what appears to be the same root cause.

Environment

  • openclaw 2026.4.26
  • macOS 15 (Darwin 25.4.0)
  • Auth: ChatGPT OAuth (access_token still valid; not an auth failure)
  • Triggering plugin: active-memory (memory-flush bootstrap run)
  • Affected models: openai-codex/gpt-5.4, openai-codex/gpt-5.5

Root cause (suspected)

buildOpenAIResponsesParams in provider-stream-*.js:

```js const messages = convertResponsesMessages(model, context, ..., { includeSystemPrompt: !isCodexResponses, // codex skips system msg supportsDeveloperRole }); const params = { model: model.id, input: messages, // empty when caller has no user turn stream: true, ...isCodexResponses ? { instructions: buildOpenAICodexResponsesInstructions(context) } : {}, ... }; ```

For codex, the system prompt is moved out of messages into instructions (correct per ChatGPT's codex contract). But if the caller passes { systemPrompt: "...", messages: [] } — which active-memory's flush bootstrap does — params.input ends up as []. The codex backend treats that as missing and 400s.

Proposed fix

Inside buildOpenAIResponsesParams, after the convertResponsesMessages call, ensure codex requests carry at least one input item when the only content available is the system prompt:

```js if (isCodexResponses && messages.length === 0 && context.systemPrompt) { messages.push({ role: "user", content: [{ type: "input_text", text: sanitizeTransportPayloadText( stripSystemPromptCacheBoundary(context.systemPrompt) ) }] }); } ```

Alternatives considered:

  • Set includeSystemPrompt: true for codex unconditionally — wrong, the ChatGPT codex backend expects system-as-instructions, not as a message.
  • Refuse to dispatch when messages.length === 0 — surfaces a clearer error but doesn't restore functionality for the (legitimate) bootstrap case.

Repro

  1. Configure an openai-codex provider with gpt-5.5 (or any openai-codex-responses model).
  2. Enable active-memory plugin, set plugins.entries.active-memory.config.activeProvider = openai-codex, activeModel = gpt-5.5.
  3. Trigger an active-memory flush (e.g. send a Slack message that crosses the flush threshold).
  4. Observe `[agent/embedded] embedded run failover decision: ... reason=timeout from=openai-codex/gpt-5.5` in `gateway.err.log`.
  5. Occasionally a single entry surfaces the underlying 400 rawError above.

Workaround

Point active-memory's activeProvider/activeModel at any non-codex provider (e.g. an lmstudio-served model). Confirms codex is the isolated failure point.

extent analysis

TL;DR

The proposed fix involves modifying the buildOpenAIResponsesParams function to ensure codex requests carry at least one input item when the only content available is the system prompt.

Guidance

  • Verify that the issue is indeed caused by the openai-codex provider and the active-memory plugin by reproducing the error using the provided repro steps.
  • Apply the proposed fix by adding the suggested code snippet to the buildOpenAIResponsesParams function to handle the case where messages is empty and context.systemPrompt is set.
  • Test the fix by triggering an active-memory flush and observing the logs for any errors or timeouts.
  • If the issue persists, try the workaround by pointing active-memory's activeProvider/activeModel at a non-codex provider to isolate the failure point.

Example

if (isCodexResponses && messages.length === 0 && context.systemPrompt) {
  messages.push({
    role: "user",
    content: [{
      type: "input_text",
      text: sanitizeTransportPayloadText(
        stripSystemPromptCacheBoundary(context.systemPrompt)
      )
    }]
  });
}

Notes

The proposed fix assumes that the buildOpenAIResponsesParams function is the root cause of the issue. If the issue persists after applying the fix, further investigation may be necessary to identify the underlying cause.

Recommendation

Apply the proposed fix to the buildOpenAIResponsesParams function to ensure codex requests carry at least one input item when the only content available is the system prompt. This should resolve the issue and prevent timeouts.

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 - ✅(Solved) Fix openai-codex provider sends empty input[] when context has only systemPrompt → ChatGPT 400 [1 pull requests, 1 comments, 2 participants]