openai / openai/codex

turn/steer can succeed without persisting input while sampling is in flight

Open
#40,805 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app-server bug
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

What issue are you seeing?

turn/steer can return a successful response for the active turn while the submitted input remains only in the pending-input queue. If the current sampling request does not complete, Codex emits neither the correlated steered-user item/started nor item/completed lifecycle before the run is stopped.

I observed this through app-server v2 with rust-v0.148.0 (3ba0f711642a888aec92a611a3f3b2211157ff89) on macOS arm64. Source inspection shows the relevant acceptance and sampling ordering is unchanged in the latest rust-v0.149.1 release and current main (3e4707b34b16e139fcb7ad11ab8445993b62bba1).

In a bounded reproduction:

  • turn/start entered a regular active turn.
  • Exactly one turn/steer request was sent with expectedTurnId and clientUserMessageId.
  • The server returned success with the expected active turnId.
  • The active sampling request remained in flight for more than six minutes.
  • No correlated steered-user item/started or item/completed was emitted before the run was stopped.
  • The client therefore could not distinguish durable acceptance from volatile queueing and treated the result as ambiguous/no-retry.

No raw prompt, model output, credential, workspace path, or identifier is included in this report.

What steps can reproduce the bug?

A deterministic model-server test can reproduce this without relying on provider timing:

  1. Start app-server and a regular turn against a controlled model server.
  2. Hold the turn's first sampling response open.
  3. While that sampling request is in flight, send one turn/steer request with fixed expectedTurnId and clientUserMessageId values.
  4. Observe that turn/steer returns the active turnId successfully.
  5. Keep the first sample blocked and observe that no correlated user-message lifecycle is persisted or emitted.
  6. Release the sample and verify the steer is eventually observed exactly once.

The current source ordering explains the behavior:

This permits a successful response with no durable user-item lifecycle for as long as the current sampling request remains in flight.

What is the expected behavior?

An accepted steer should not remain indefinitely volatile behind one long-running sampling request. A successful turn/steer response should provide a durable, reconcilable acceptance boundary. For example, Codex could either:

  1. return success only after the steered input is durably recorded and its correlated lifecycle can be observed; or
  2. durably expose a queued-steer state keyed by clientUserMessageId, while ensuring the active turn reaches a safe steer-processing boundary without waiting indefinitely for the current provider request.

The fix should avoid cancelling tool side effects, duplicating delivery, or manufacturing a user-item lifecycle before persistence.

Additional information

Related but distinct work:

  • #32254 requests durable/idempotent acceptance keyed by clientUserMessageId.
  • #30341 preserves a steer accepted during turn finalization.
  • #29582 concerns model semantics after pending steer input is drained.

This report is specifically the pre-persistence liveness case: the RPC succeeds, but a long in-flight sample prevents the accepted input from reaching its correlated durable lifecycle.

A regression should also cover interrupt, finalization, retry with the same ID and payload, and conflicting reuse of the same ID with different input. I would be happy to prepare a focused patch if maintainers agree on the intended durable-acceptance contract and safe sampling boundary.

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 with codex-rs/core/src/session/turn_input.rs, especially steer_input, and codex-rs/core/src/session/turn.rs around pending-input draining and run_sampling_request. Reproduce the ordering with the deterministic model-server test described in the issue. Done means the chosen durable-acceptance contract is implemented without duplicate delivery, and regression coverage includes interrupt, finalization, retries, and conflicting clientUserMessageId reuse.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend, backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.