fix(agent): fail closed when Codex account-model entitlement 400s exhaust the chain
A Codex ChatGPT-account 400 ('The X model is not supported when using Codex
with a ChatGPT account.') names the model, so with a single credential the
slug is dead for that account. The fallback walk still re-selected it and
restore_primary_runtime switched back to the primary at the start of every
turn, announcing an unverified 'Primary model restored' — the two warnings
alternated forever with zero delivered answers (#106475).
Record the rejected (provider, model) pair on the non-retryable client-error
path (only when no multi-credential pool exists — rotation covers that case,
#71970), skip rejected entries during the fallback walk, and gate
restore_primary_runtime on the primary's slug so the session fails closed
with the terminal entitlement error instead of oscillating. Fixes #106475.
(cherry picked from commit 471435b10288f15387b2549a8b02551d82c0f670)
This commit is contained in:
@@ -282,6 +282,10 @@ def settle_unrecovered_error(
|
||||
) and not is_context_length_error
|
||||
|
||||
if is_client_error:
|
||||
# A Codex ChatGPT-account entitlement 400 names the model: with nothing to rotate the
|
||||
# slug is dead for this account, so record it before the fallback walk runs (#106475).
|
||||
from agent.chat_completion_helpers import _mark_entitlement_rejected_model
|
||||
_mark_entitlement_rejected_model(agent, api_error)
|
||||
# Copilot self-heal BEFORE fallback: a stale credential yields a 400
|
||||
# ``model_not_available_for_integrator`` / ``model_not_supported``, not a 401.
|
||||
# Fresh token + client rebuild, one retry, SAME provider.
|
||||
|
||||
Reference in New Issue
Block a user