`wait_agent` and `close_agent` report `completed: null` when a child `TurnComplete` contains an error
What version of Codex CLI is running?
codex-cli 0.146.0
What subscription do you have?
ChatGPT-authenticated Codex environment. The exact subscription tier is not
exposed by the diagnostics used for this report.
Which model were you using?
gpt-5.6-sol, high reasoning effort.
What platform is your computer?
Linux 6.17.0-1019-aws x86_64
What terminal emulator and version are you using?
Interactive Codex TUI. The terminal emulator is not relevant to this
reproduction.
Codex doctor report
Not included in this draft. The affected parent and child rollout records are
available and contain the complete lifecycle evidence.
What issue are you seeing?
A spawned child failed its first model request. Its terminal task_complete
event correctly contained an error and no final assistant message:
{
"type": "task_complete",
"last_agent_message": null,
"error": {
"message": "Item 'msg_<redacted>' of type 'message' was provided without its required 'reasoning' item: 'rs_<redacted>'.",
"codex_error_info": "other"
}
}
The same child then had three contradictory externally visible statuses:
subagent notification: errored(<actual API error>)
wait_agent: completed: null
close_agent: previous_status.completed: null
wait_agent also returned timed_out: false, so a caller can mistake a failed
child for a successfully completed child with an empty result.
Affected child thread:
019fc932-41a0-7201-90fb-a1a82d218364
What steps can reproduce the bug?
- Start Codex with MultiAgent V1 enabled.
- Spawn a child that reaches a terminal
TurnCompleteEventwith
error: Some(...) and last_agent_message: None. One deterministic way on
0.146.0 is the currently reported fork_context=true reasoning-dependency
failure from #33329.
- Call
wait_agentfor the child. - Observe that the asynchronous child notification reports
erroredwhile
wait_agent reports completed: null.
- Call
close_agentfor the same child. - Observe that
previous_statusis alsocompleted: null.
What is the expected behavior?
TurnCompleteEvent { error: Some(error), ... }must derive
AgentStatus::Errored(error.message).
wait_agentmust return the errored status and mark the wait tool call as
failed.
close_agent.previous_statusmust report the same errored status.- Notifications, wait results, close results, and persisted lifecycle state must
agree on the terminal outcome.
Additional information
Root cause
TurnCompleteEvent now has an optional terminal error field:
That field was added in#32280 so unsuccessful turns can
carry terminal error details.
However, the multi-agent status reducer still maps every TurnComplete toCompleted(last_agent_message) and ignores ev.error:
EventMsg::TurnComplete(ev) =>
Some(AgentStatus::Completed(ev.last_agent_message.clone())),
Both wait_agent and close_agent consume this derived watched status, which
explains why both return Completed(None) even though the terminal event carries
an error.
The status reducer predates TurnCompleteEvent.error. When #32280 added the
new field, its status test was updated only with error: None; no non-null error
case was added:
Suggested fix and regression coverage
Map an errored completion before the successful-completion case:
EventMsg::TurnComplete(ev) => match &ev.error {
Some(error) => Some(AgentStatus::Errored(error.message.clone())),
None => Some(AgentStatus::Completed(ev.last_agent_message.clone())),
},
Add tests that assert:
TurnComplete(error=Some, last_agent_message=None)derivesErrored.wait_agentreturns that errored status and a failed collab tool status.close_agent.previous_statusreturns the same error.- The asynchronous completion notification and tool results agree.
Duplicate search
No issue with this exact TurnCompleteEvent.error -> Completed(None) root cause
was found.
Related but distinct:
#25619covers app-server
turns that silently complete without a wire-visible error. In this case the
terminal error is present; only the multi-agent status reducer discards it.
#34919covers missing
multi-agent event data in exec --experimental-json, not incorrect terminal
status derivation.
#24342covers waits that
return no completed agents, not a known failed child being reported as
Completed(None).