openai / openai/codex

External GitHub write succeeds but Codex terminates on {"detail":"Bad Request"} without state reconciliation

Open
#40,083 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

codex-web enhancement tool-calls
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

Summary

Codex can terminate a task after an external GitHub mutation returns:

{"detail":"Bad Request"}

while the mutation has in fact succeeded remotely.

In this case, Codex was creating a draft pull request. The UI/session reported the Bad Request and stopped, but GitHub had successfully created the PR. Codex did not reconcile authoritative remote state before terminating.

This appears related to the existing Bad Request / recovery family of issues, including #30890, #32889, #33372, and #14253, but this report is specifically about ambiguous side-effecting writes and the need for post-error state reconciliation.

Reproduction observed

Codex was asked to isolate and publish a narrow Backend fix.

The flow was:

  1. Create a clean worktree from current Backend main.
  2. Isolate a two-file fix.
  3. Run focused tests and the service-identity suite.
  4. Commit the change.
  5. Push branch.
  6. Create a draft PR.
  7. Codex displayed:
Ran commands

{"detail":"Bad Request"}
  1. The task then stopped.

However, GitHub authoritative state showed that the PR had been successfully created:

  • Repository: Begetterz/Pardnafi_Backend
  • PR: #173
  • Title: fix: recover concurrent operator identity binding
  • Head branch: fix/inc-001-operator-identity-race
  • Head SHA: 1f86369661746987cefb238c06722671b8718e2e
  • State: open
  • Draft: true
  • Mergeable: true
  • Commits: 1
  • Changed files: 2

The PR creation timestamp was consistent with the attempted Codex operation.

Expected behaviour

A side-effecting external mutation should not be treated as definitely failed merely because the client/tool response is an error, timeout, disconnect, empty response, or otherwise ambiguous.

After an ambiguous result, Codex should reconcile against the authoritative remote system before stopping or retrying.

For example, for PR creation:

CREATE PR
  -> error / timeout / unknown
  -> query GitHub by expected head branch / base / title
  -> if PR exists and expected head SHA matches: adopt remote state and continue
  -> if PR does not exist: retry only if the mutation is safe/idempotent

Likewise for merge/close/create-issue/tag/release and other side-effecting operations.

Why this matters

Without reconciliation, Codex can produce two unsafe outcomes:

  1. False failure / abandoned workflow

    • the external operation succeeded, but Codex stops and reports failure.
  2. Duplicate or conflicting writes on retry

    • a user or agent retries an operation that already succeeded remotely.

For autonomous engineering workflows, this is a distributed-systems correctness issue rather than only a UI error. A failed acknowledgement does not prove a failed mutation.

Suggested recovery invariant

For every side-effecting external operation:

WRITE
  -> SUCCESS: read back authoritative state and continue
  -> ERROR / TIMEOUT / UNKNOWN:
       do not assume failure
       do not blindly retry
       read authoritative remote state
       if intended state exists, adopt it
       otherwise retry only when safe/idempotent

In short:

WRITE -> ERROR/UNKNOWN -> READ BACK -> RECONCILE -> CONTINUE

Related issues

  • #30890 — long-running task interrupted by {"detail":"Bad Request"}
  • #32889 — HTTP 400/error classification loses useful diagnostic information
  • #33372 — interrupted external-write state can diverge from the external system
  • #14253 — poor recovery after tool errors

Additional evidence

After manual reconciliation, the created PR was healthy and mergeable; its remote CI run completed successfully. This strongly suggests the write itself succeeded and only the acknowledgement/error path caused Codex to terminate.

I can provide the exact Codex transcript around the failing operation if useful.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the GitHub draft-PR creation path and the error/recovery handling described here, using PR #173 and related issues #30890, #32889, #33372, and #14253 as behavioral context. Done means ambiguous write results are reconciled with authoritative GitHub state before termination or retry, covering the reported success and error cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
github, rust
Domain
devtools, distributed-systems
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.