When Roo Code connects to a third-party API, most errors are not model-capability problems but issues with provider selection, Base URL, keys, rate limits, or the network: a 401 right after setup, a 404 after changing the address, a 429 halfway through a long task, or streaming that hangs until timeout. The order of handling is to check the status code and error type first, then the request-id, and only then change the prompt. This article separates 401, 404, 429, context overflow, and timeouts, with troubleshooting steps, a log checklist, and sample code. Models and billing are governed by model pricing.
1. Start with layers: where the error occurs
A request passes through the Roo Code client, the VS Code extension host, the network and proxy, the gateway, and the upstream model. The same 401 may be a wrong key or a provider protocol mismatch; the same 404 may be an extra /v1 in the path or a model ID that does not exist. Layer the problem first so you do not keep changing settings in the wrong direction.
| Status | Error type | Common cause | What to do |
|---|---|---|---|
| 400 | invalid_request_error | Parameters, context length, or spending limit | Fix the request or limit, then retry |
| 401 | authentication_error | Missing, wrong, or expired key; auth header mismatch | Fix credentials; do not retry |
| 402 | billing_error | Billing or balance problem | Check billing |
| 403 | permission_error | Key lacks model or project permission | Check authorization |
| 404 | not_found_error | Wrong path or model ID | Check the Base URL and model name |
| 413 | request_too_large | Request body exceeds the endpoint limit | Compress or split the request |
| 429 | rate_limit_error | Rate, concurrency, or spending cap | Back off, then retry |
| 500 | api_error | Server-side error | Back off and retry |
| 504 | timeout_error | Processing timeout | Switch to streaming or batch the work |
Keep the request-id from the response headers or error body. Log at least the time, status code, error type, model ID, and request ID; never log full keys or sensitive code.
2. 401: provider, key, and auth header
In Roo Code, the provider dropdown and the key field are separate, so the most common 401 is not an invalid key but a mismatched combination: an OpenAI-compatible key entered into the Anthropic provider, or the reverse; a Base URL pointing at environment A while the key belongs to environment B; or an old key left behind after switching API configuration profiles.
Other common causes: spaces, line breaks, quotes, or full-width characters around the key; a key that was deleted, expired, or belongs to another workspace; a corporate proxy rewriting or stripping the Authorization header; and subscription login and API key configured at the same time in one extension.
Troubleshooting order:
- Confirm the provider type matches the Base URL protocol: OpenAI-compatible uses
/v1/chat/completions, Anthropic uses/v1/messages. - Send one minimal request directly from the terminal with the same key and Base URL.
- If the direct request succeeds but Roo Code fails, the problem is in provider configuration, the profile, or a proxy; if the direct request also fails, the problem is the key, gateway, or network.
- Cross-check with a new key to rule out a copy-paste issue.
Do not retry a 401; retries only amplify logs and alerts.
3. 404: Base URL path and model ID
A 404 has two families: the path does not exist, or the model does not exist.
Path problems: the Base URL for an OpenAI-compatible provider usually ends at /v1, and the client appends /chat/completions. If you enter the full /v1/chat/completions, the actual path may be duplicated. A trailing slash, double slash, case difference, or stray space can also cause a 404. The Anthropic provider appends /v1/messages, so an OpenAI-compatible address entered there will also return 404.
Model problems: when the error contains model not found, invalid model, or The model does not exist, copy the exact ID from the gateway's model list or pricing page. Model aliases, date suffixes, and capitalization may differ; some gateways require a provider prefix. Also confirm the key has permission for that model; insufficient permission sometimes returns 403 and sometimes 404.
Quick check: call /v1/models to see the models visible to the current key, then send a minimal request with an ID from that list.
4. 429: rate limits, quotas, and retry storms
A 429 means the request exceeded a rate, concurrency, or spending limit. Common causes:
- Requests per minute or tokens per minute exceeded;
- Multiple tools or colleagues sharing one key;
- Roo Code Orchestrator subtasks or parallel tool calls raising instantaneous concurrency;
- Retries without backoff, creating a retry storm;
- Account balance or workspace spending caps triggering a limit.
Check the retry-after response header first: wait as instructed if present; otherwise use exponential backoff with random jitter and set a maximum attempt count. Some quota-triggered 429 responses carry no retry-after, and waiting will not restore service; you need to top up or adjust the limit.
Watch for stacked retries: Roo Code may retry automatically, the SDK or gateway may retry, and the business layer may add another layer, multiplying actual requests. Plan client, SDK, and business retries together. Do not retry 401, 403, 404, or 400.
5. 400 and 413: context length and request body
Context overflow usually returns 400, with messages containing context length, maximum context, or prompt is too long. The model is not broken; the budget for input plus output exceeds the window.
Pay special attention to the context-window setting in Roo Code: if the manually entered window is larger than the model actually supports, the client may trim against the wrong budget or send an overlong request, resulting in a 400. Set the window to the value in the model documentation and enable context compaction or condensing if the current version supports it.
Handling order:
- Reduce the number of files read at once and provide only relevant excerpts.
- Compress terminal output and MCP tool returns, keeping only necessary fields.
- Split long documents by chapter, process in sections, then summarize.
- Clean up early conversation, keeping the system prompt, recent turns, and a summary.
- Leave room for output;
max_tokenslimits only output and cannot fix an input overflow.
A 413 request_too_large means the request body is too large, which is different from context length. Screenshots, PDFs, and base64 images trigger it most easily; compress images, reduce attachments, or split the request.
6. Timeouts and broken streams: streaming, proxies, and long tasks
Roo Code uses streaming output by default. A streaming request may return HTTP 200 and then send an error event inside the SSE event stream; a client that looks only at the status code will treat a failure as success. Parse error events in the stream and confirm a normal end marker, or mark the result as incomplete.
Common sources of timeout:
- Corporate proxies, VPNs, or TLS interception causing an unstable connection;
- DNS, IPv6, firewall, or MTU problems;
- A single request running too long, with an idle connection disconnected;
- A long agent task continuously running tools, with cumulative time exceeding the client or gateway limit;
- Upstream model queuing, with a very slow first byte.
Prefer streaming; set a reasonable timeout for each request; split long tasks into stages; reduce the scope of auto-approved tools; and switch networks or use a phone hotspot to quickly determine whether the local network is at fault. Corporate TLS interception requires VS Code and the system to trust the relevant CA, and Node-based clients sometimes also need NODE_EXTRA_CA_CERTS.
7. Logs and support: how to explain the problem
Do not send only "it errored". Collect information with this checklist:
- Time of occurrence, time zone, and duration.
- Roo Code version, VS Code version, and operating system.
- Provider type, Base URL (domain only), and model ID.
- Whether streaming was used, request duration, and retry count.
- HTTP status code, error type, and the full error message.
request-id, which may appear in both headers and body.- Scope: one machine, one project, one network, or the whole team.
- Minimal reproduction: a curl command or a minimal repository, plus the result of the same request against the official endpoint.
Log locations: find the Roo Code channel in VS Code's Output panel; extension-host and MCP tool errors may appear in the Developer Tools console; for gateway-side issues, send the request-id to gateway support. After the main repository was archived, GitHub issues may be read-only, so check the support channel of the community fork you use. Redact logs specifically: keep only the first four and last four characters of a key, and handle prompts and code according to company policy.
8. Example: decide whether to retry by error type
The following uses an OpenAI-compatible interface: 401 and 404 fail immediately, while 429, 5xx, and timeouts retry with backoff. It works as a standalone script to reproduce a problem and can also be dropped into a batch job.
import os
import random
import time
from openai import (
APIConnectionError,
APIStatusError,
APITimeoutError,
AuthenticationError,
NotFoundError,
OpenAI,
RateLimitError,
)
client = OpenAI(
base_url=os.environ["OPENAI_BASE_URL"],
api_key=os.environ["OPENAI_API_KEY"],
)
def ask(prompt: str, retries: int = 4) -> str:
for attempt in range(retries):
try:
resp = client.chat.completions.create(
model=os.environ["OPENAI_MODEL"],
messages=[{"role": "user", "content": prompt}],
timeout=120,
)
return resp.choices[0].message.content or ""
except AuthenticationError as exc:
raise SystemExit(f"401: check the provider, key, and auth header; request-id={exc.request_id}") from exc
except NotFoundError as exc:
raise SystemExit(f"404: check the Base URL and model ID; request-id={exc.request_id}") from exc
except RateLimitError:
wait = min(2 ** attempt, 20) + random.random()
print(f"429: retrying in {wait:.1f}s")
time.sleep(wait)
except (APITimeoutError, APIConnectionError):
wait = min(2 ** attempt, 10) + random.random()
print(f"Timeout or connection failure: retrying in {wait:.1f}s")
time.sleep(wait)
except APIStatusError as exc:
if exc.status_code >= 500:
wait = min(2 ** attempt, 20) + random.random()
print(f"{exc.status_code}: retrying in {wait:.1f}s")
time.sleep(wait)
continue
raise
raise RuntimeError("Retries exhausted; fall back or alert")
print(ask("Reply with OK only"))
The example does not set the SDK retry count explicitly; in production, configure SDK default retries and business retries together. The Base URL is usually https://ai.zhongshangqihang.com/v1, and the model ID is copied from model pricing.
FAQ
Does a 401 always mean a wrong key?
Not necessarily. A mismatched provider type, a Base URL pointing at the wrong environment, or a proxy rewriting the auth header can all return 401. Test directly with the same key and Base URL first, then check Roo Code's provider and configuration profile.
A 404 says model not found. How do I confirm the model ID?
Call /v1/models to get the list visible to the current key, copy the exact ID, and do not type it from memory. Then confirm the Base URL does not duplicate the path and the provider protocol matches.
Will a 429 always recover after waiting?
Not necessarily. Rate limits usually recover; a 429 triggered by quota or balance may not include retry-after, and waiting is pointless, so adjust the limit or top up. Check the error type and headers before deciding.
Is context overflow a model problem?
Usually not. It means the input-plus-output budget exceeds the window, or Roo Code's context-window setting is larger than the model's real value. Reducing input, enabling compaction, and splitting tasks are more direct than switching models.
A streaming request returns 200 and then breaks. Is that success?
No. A streaming response may send an error event over SSE after the 200. The client must parse the event stream and confirm a normal end; otherwise mark the result incomplete and retry or alert.
Next steps
Create a test key at ZSQH AI Gateway, rehearse 401, 404, 429, and timeout once each with the curl command and script above, and then connect production monitoring. Model availability and billing are governed by model pricing.
Related reading:
- OpenAI API Errors and Rate-Limit Troubleshooting
- Claude Code API Guide: Keys, Base URL, and Integration
- What Is an AI API Relay? A Complete 2026 Guide
Note: Roo Code, Cline, Cursor, Claude Code, Anthropic, and OpenAI are trademarks or registered trademarks of their respective owners. This article is a technical troubleshooting note and implies no affiliation or partnership with those companies. Error types and client behavior change between versions; defer to official documentation and repository announcements.
