Guardian infrastructure failures still surface as high-risk denials after retries are exhausted
What version of Codex CLI is running?
The user-facing failure was observed on codex-cli 0.142.5. The same terminal-status defect remains in main at b1373b74.
What subscription do you have?
Pro
Which model were you using?
gpt-5.6-sol
This was the user-selected parent-session model at the recorded failures. The internal Guardian reviewer model was not exposed, so this field does not identify which reviewer model returned the capacity error.
What platform is your computer?
Microsoft Windows NT 10.0.19045.0 x64
The affected status mapping is platform-independent.
What terminal emulator and version are you using (if applicable)?
Windows Terminal 1.24.11911.0 with PowerShell 7.6.4 (Core, x64).
Codex doctor report
Not included. The failure occurs after the parent session is running, inside the Guardian review lifecycle. The deterministic reproduction uses a mock provider response and does not depend on installation, authentication, terminal, MCP, or state-database health.
What issue are you seeing?
When automatic approval review fails before producing a risk assessment, Codex correctly keeps the requested action blocked, but reports the terminal result as though Guardian had made a substantive high-risk denial:
Automatic approval review denied (risk: high, authorization: unknown):
Automatic approval review failed: Selected model is at capacity. Please try a different model.
This occurred repeatedly after the reviewer exhausted its attempts. The same misleading status was also observed when the remote review/compaction task failed. In both cases no Guardian assessment had classified the requested action as high risk.
Bounded retries for transient reviewer failures were merged in #27062. The remaining defect is the terminal state after those retries are exhausted. Current main records that condition as FailedClosed internally, but then constructs a public High / Unknown / Deny assessment:
- Internal
FailedClosedfollowed by the synthetic public denial: https://github.com/openai/codex/blob/b1373b74a27d1d9b65074a873202683355cae772/codex-rs/core/src/guardian/review.rs#L542-L566 - Core status enum without
Failed: https://github.com/openai/codex/blob/b1373b74a27d1d9b65074a873202683355cae772/codex-rs/protocol/src/approvals.rs#L111-L119 - App-server status enum without
Failed: https://github.com/openai/codex/blob/b1373b74a27d1d9b65074a873202683355cae772/codex-rs/app-server-protocol/src/protocol/v2/item.rs#L447-L457
This report is not asking Codex to fail open. Blocking the action is correct when no assessment is available. The bug is representing an infrastructure or protocol failure as if an actual high-risk judgment occurred.
What steps can reproduce the bug?
Deterministic source-level reproduction:
- Configure
approvals_reviewer = "auto_review"and request a command or patch that requires approval. - Make each Guardian review attempt return a provider failure such as
server_is_overloadedwithSelected model is at capacity. - Let the existing bounded retry budget run out.
- Observe a terminal Guardian assessment reported as
Denied, withrisk=Highandauthorization=Unknown, even though no assessment payload was produced. - Observe the blocked target item represented as declined rather than failed.
A focused integration test can use the existing mock Responses server and assert both that the action never executes and that the terminal review status is Failed with no assessment fields.
What is the expected behavior?
- Keep the target action blocked (fail closed).
- Emit a distinct terminal Guardian status such as
Failed. - Omit
riskLevelanduserAuthorizationbecause no assessment supplied either value. - Preserve the underlying provider, transport, runtime, prompt-construction, or parsing error in
rationale. - Map the blocked target item to an execution failure, not a user or policy decline.
- Keep analytics, replay, TUI, Desktop, and app-server lifecycle status consistent.
Additional information
This status design is prior work, not a new proposal from this report:
- #27072 implemented a truthful
Failedterminal status across core, protocol, app-server, replay, TUI, schemas, analytics, and tests, but was closed without being merged. - #27540 handled exhausted capacity failures as reviewer unavailability rather than denial, but was also closed without being merged.
- #27062 merged bounded retries for transient reviewer failures; it does not fix the terminal public status after all retries fail.
- #15341 reported an older instance of the same misleading user-facing status, but was closed after its particular upstream request failure was addressed.
- #37392 reports a current parse-failure trigger involving malformed reviewer JSON. Validating or retrying malformed output is complementary; if all attempts fail, the terminal status still needs to represent that no policy assessment was produced.
After a broader review of the earlier implementation work, this issue is being closed as a separate tracker. The corrected reproduction details and current-main source references are retained here as supporting evidence.
2 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
I reviewed #37392 and the earlier Guardian work more broadly. #37392 reports one concrete trigger: malformed reviewer JSON with duplicate fields. Validating or retrying that malformed output is useful, but if every attempt still fails, the public lifecycle must distinguish “no assessment was produced” from an actual policy denial.
#27062 merged bounded retries for transient reviewer failures. #27072 previously implemented the distinct
Failedterminal status, and #27540 addressed exhausted capacity failures, but neither of those terminal-status changes was merged. Currentmainstill records the condition asFailedClosedinternally while publishingDeniedwithHighrisk andUnknownauthorization.I updated this issue to credit that prior work and to correct the observed parent-session model. I am keeping it open only as the unresolved generic terminal-status tracker; it is not intended to claim a new status design or replace #37392's trigger-specific report.