Skip to content

Codex owns the retry - #195

Merged
vitramir merged 1 commit into
mainfrom
fix/codex-owns-its-retries
Aug 19, 2026
Merged

Codex owns the retry#195
vitramir merged 1 commit into
mainfrom
fix/codex-owns-its-retries

Conversation

@vitramir

Copy link
Copy Markdown
Contributor

A codex error notification carries will_retry — whether codex is retrying the turn itself. The daemon parsed it, logged it, and then ignored it, deciding instead by substring:

var retryableCodexErrorNotificationTerms = [...]string{
	"stream disconn", "stream disconnected", "connection reset", ...
}

What that cost

A response that completes carrying no assistant message is reported as stream disconnected before completion with will_retry=false. That is an ordinary thing for a model to return — captured live on a platform VM, every stream reaching the proxy ended response.completed with zero output_text.delta events, and metering recorded them success with real output tokens.

The daemon matched "stream disconn", overruled codex, and restarted the turn under a new id. Same request, same answer, again — six turns for one message, backing off 1s, 2s, 4s, 8s, ending in produced no text:

codex bridge: error notification: ... will_retry=false message=stream disconnected before completion
codex turn transient failure: ... retrying sync
sync messages retry failed: ... retrying in 1s
... x6
codex turn ... produced no text for message ...

Change

notification before after
transient term, will_retry=true retry retry
transient term, will_retry=false retry storm turn ends: nothing posted, message acked
no matching term terminal terminal

Scoped to the transient class on purpose: gating on will_retry alone also swallows notifications matching none of the terms, which an existing test caught, so those stay terminal.

Not in this PR

retryableCodexErrorNotificationTerms is an allowlist, so a transient failure codex words differently still exits the daemon. will_retry answers that half too and would retire the list entirely — worth doing, deliberately not widened here.

A codex error notification says whether codex is retrying the turn
itself, and the daemon ignored it: any message containing one of eight
substrings was retried, will_retry or not. A response that completes
carrying no assistant message is reported that way and is an ordinary
thing to return, so one message became six turns, each under a new id,
backing off 1s 2s 4s 8s, every one of them asking the same question and
getting the same answer.

A transient notification codex has stopped retrying now ends the turn
the way an empty turn ends: nothing posted, message acked, one line
logged. While codex is retrying, the daemon still resyncs behind it, and
a notification matching none of the terms is still terminal.
@vitramir
vitramir force-pushed the fix/codex-owns-its-retries branch from 030fc6c to add2fae Compare August 19, 2026 03:31
@vitramir
vitramir merged commit 389803f into main Aug 19, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant