[eric] models: track model errors (diagnostic) + friendly 'not on your plan' card for the 1211 unknown-model wall

This commit is contained in:
ciregenz
2026-06-10 19:10:57 -07:00
parent 0bf2eb37f6
commit 100d6491f7
3 changed files with 66 additions and 0 deletions
+36
View File
@@ -32,6 +32,7 @@ from backend.apps.agents.core.error_classify import (
_is_auth_error,
_is_long_context_error,
_is_transient_capacity_error,
_is_unknown_model_error,
)
from backend.apps.agents.manager.session.session_store import (
_delete_session_file,
@@ -3009,7 +3010,42 @@ class AgentManager:
"session_id": session_id,
"message": error_msg.model_dump(mode="json"),
})
elif _is_unknown_model_error(e, extra_text=_stderr_tail):
# Upstream rejected the model code itself (e.g. Codex 1211 on a
# ChatGPT plan that lacks our GPT ids). Track it; the friendly
# "add an API key / pick another model" card is rendered frontend-side.
try:
from backend.apps.service.client import submit_diagnostic
submit_diagnostic({
"kind": "model_error",
"subkind": "unknown_model",
"model": session.model,
"provider": session.provider,
"connection_mode": getattr(load_settings(), "connection_mode", "own_key"),
"error_preview": (str(e) or "")[:400],
})
except Exception:
logger.debug("submit_diagnostic model_error failed", exc_info=True)
error_msg = Message(role="system", content=f"Error: {str(e)}", branch_id=session.active_branch_id)
session.messages.append(error_msg)
await ws_manager.send_to_session(session_id, "agent:message", {
"session_id": session_id,
"message": error_msg.model_dump(mode="json"),
})
else:
# Track unclassified agent failures too so we stop flying blind on them.
try:
from backend.apps.service.client import submit_diagnostic
submit_diagnostic({
"kind": "model_error",
"subkind": "unclassified",
"model": session.model,
"provider": session.provider,
"connection_mode": getattr(load_settings(), "connection_mode", "own_key"),
"error_preview": (str(e) or "")[:400],
})
except Exception:
logger.debug("submit_diagnostic model_error failed", exc_info=True)
error_msg = Message(role="system", content=f"Error: {str(e)}", branch_id=session.active_branch_id)
session.messages.append(error_msg)
await ws_manager.send_to_session(session_id, "agent:message", {
@@ -77,6 +77,26 @@ def _is_auth_error(exc: BaseException, extra_text: str = "") -> bool:
))
def _is_unknown_model_error(exc: BaseException, extra_text: str = "") -> bool:
"""True when the upstream rejects the model code itself (e.g. a ChatGPT/Codex
subscription whose plan doesn't expose the GPT model id we send: code 1211
'Unknown Model, please check the model code'). The fix isn't retry, it's a
different model or an API key, so we surface that instead of the raw JSON.
"""
combined = f"{exc!s}\n{extra_text}".strip()
if not combined:
return False
return bool(re.search(
r"unknown\s+model"
r"|check\s+the\s+model\s+code"
r"|\b1211\b"
r"|model[_\s-]?not[_\s-]?found"
r"|does\s+not\s+exist.*model|model.*does\s+not\s+exist",
combined,
re.IGNORECASE,
))
def _is_transient_capacity_error(exc: BaseException, extra_text: str = "") -> bool:
# The Claude CLI's underlying ProcessError stringifies to a generic
# "Command failed with exit code 1 / Check stderr output for details";
@@ -101,6 +101,16 @@ function parseOpenSwarmError(text: string, ctx?: OverflowContext): OpenSwarmErro
ctaAction: 'upgrade',
};
}
if (/unknown model|check the model code|\b1211\b|model_not_found/i.test(text)) {
return {
kind: 'auth',
title: "That model isn't available on your plan",
detail:
"Your connected subscription doesn't include this model. Add an API key for it in Settings, or pick a different model.",
ctaLabel: 'Open Settings',
ctaAction: 'settings',
};
}
if (/at capacity|Try again shortly|503|service unavailable/i.test(text)) {
return {
kind: 'network',