Bug type
Behavior bug (incorrect output/state without crash)
Summary
When Poe API returns HTTP 402 with "You've used up your points!", OpenClaw does not recognize it as a billing error, so model fallback never triggers and users see the raw error instead of switching to fallback models.
Steps to reproduce
- Configure Poe as primary model with OpenRouter fallbacks in
agents.defaults.model.
- Ensure Poe API key has exhausted points (or simulate 402 response).
- Send a message to trigger an LLM request.
- Observe that Poe returns
402 You've used up your points! Visit https://poe.com/api/keys to get more.
Expected behavior
OpenClaw should classify the 402 error as billing, trigger model fallback to the next model in agents.defaults.model.fallbacks, and continue responding without showing the raw error to the user.
Actual behavior
Fallback does not trigger. The user sees the raw error message:
402 You've used up your points! Visit https://poe.com/api/keys to get more.
No automatic switch to fallback models occurs.
OpenClaw version
2026.3.8
Operating system
macOS (darwin 24.6.0)
Install method
npm global
Model
poe/GPT-5.3-Codex
Provider / routing chain
openclaw -> poe (api.poe.com) -> GPT-5.3-Codex
Config file / key location
No response
Additional provider/model setup details
Poe provider uses OpenAI-compatible API (api: "openai-completions").
Fallback models are OpenRouter-based and are in agents.defaults.models allowlist.
Logs, screenshots, and evidence
# Session assistant message with error
stopReason: "error"
errorMessage: "402 You've used up your points! Visit https://poe.com/api/keys to get more."
provider: "poe"
model: "GPT-5.3-Codex"
Impact and severity
- Affected: Users with Poe as primary model and configured fallbacks
- Severity: Medium–High (blocks replies when Poe points are exhausted)
- Frequency: 100% when Poe returns 402
- Consequence: Users cannot get responses until they top up Poe or manually switch models; fallback chain is effectively unusable
Additional information
Root cause
In classifyFailoverReason, 402 handling depends on classifyFailoverReasonFrom402Text, which uses RAW_402_MARKER_RE:
const RAW_402_MARKER_RE = /...|^\s*402\s+payment required\b/i;
This only matches 402 payment required at the start. Poe's format is 402 You've used up your points!, so the regex does not match.
Proposed fix
extractLeadingHttpStatus already parses "402 You've used up your points!..." correctly. Add an early check in classifyFailoverReason (e.g. after classifyFailoverReasonFrom402Text):
const leadingStatus = extractLeadingHttpStatus(raw.trim());
if (leadingStatus?.code === 402) return classify402Message(raw);
Related
Bug type
Behavior bug (incorrect output/state without crash)
Summary
When Poe API returns HTTP 402 with "You've used up your points!", OpenClaw does not recognize it as a billing error, so model fallback never triggers and users see the raw error instead of switching to fallback models.
Steps to reproduce
agents.defaults.model.402 You've used up your points! Visit https://poe.com/api/keys to get more.Expected behavior
OpenClaw should classify the 402 error as billing, trigger model fallback to the next model in
agents.defaults.model.fallbacks, and continue responding without showing the raw error to the user.Actual behavior
Fallback does not trigger. The user sees the raw error message:
No automatic switch to fallback models occurs.
OpenClaw version
2026.3.8
Operating system
macOS (darwin 24.6.0)
Install method
npm global
Model
poe/GPT-5.3-Codex
Provider / routing chain
openclaw -> poe (api.poe.com) -> GPT-5.3-Codex
Config file / key location
No response
Additional provider/model setup details
Poe provider uses OpenAI-compatible API (api: "openai-completions").
Fallback models are OpenRouter-based and are in agents.defaults.models allowlist.
Logs, screenshots, and evidence
Impact and severity
Additional information
Root cause
In
classifyFailoverReason, 402 handling depends onclassifyFailoverReasonFrom402Text, which usesRAW_402_MARKER_RE:This only matches
402 payment requiredat the start. Poe's format is402 You've used up your points!, so the regex does not match.Proposed fix
extractLeadingHttpStatusalready parses"402 You've used up your points!..."correctly. Add an early check inclassifyFailoverReason(e.g. afterclassifyFailoverReasonFrom402Text):Related