Common issues¶
A symptom-first guide. If your symptom is not here, see Routing or Providers.
"I get HTTP 403 with 'A force-free request that violates privacy policy must fail closed.'"¶
Likely cause. You sent smart-router-free, set X-Scout: true,
or otherwise tried to force the free model on a request that is
metadata.sensitive: true (the default).
Verify. Run /v1/route/decision with the same body. The cause
will be free_route_blocked_by_privacy.
Safe remediation. Switch to smart-router and let the gateway
choose, or set "metadata": {"sensitive": false} only when you are
sure the content is public.
Escalate if. The request is genuinely public and you still get 403 — that would indicate the policy file was edited incorrectly. File an incident.
See Security → Free-model policy.
"Aider says the response is empty."¶
Likely cause. DeepSeek extended-thinking reasoning-only deltas
are not being seen as content by Aider. The gateway's
_stream_with_reasoning_normalization does fold reasoning into
content, but a long reasoning passage can produce a large first
content chunk.
Verify. Look at the raw SSE stream:
curl -sN "$BASE/v1/chat/completions" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"model":"smart-router-flash","stream":true,"messages":[{"role":"user","content":"hi"}],"max_tokens":64}'
Safe remediation. Run Aider with --no-stream.
Escalate if. Empty responses happen on non-streaming calls too, which means the model itself returned empty. Re-issue the request once; if it persists, the upstream model may be having an issue.
"All requests go to Pro and we are over budget."¶
Likely cause. The high-reasoning markers (/pro,
[reasoning:high], "think deeply") are present in the user's
instructions. Or the budget soft cap has fired, in which case the
issue is the opposite — Pro is disabled and everything goes to
Flash. Check the routing logs.
Verify. Look at sgw_routing_decisions_total{action="ROUTE"}
by model. If it shows model="deepseek_v4_pro" for most requests,
inspect the input prompts for markers.
Safe remediation. Strip high-reasoning markers from the prompt template. The policy cannot tell "the user actually wants Pro" from "the template happens to contain the words think deeply". This is a client-side issue.
Escalate if. The markers are absent and the decision is still
Pro. Then a hard rule fired; check the evidence field of the
/v1/route/decision output.
"I get 401 even though I am sending Authorization."¶
Likely cause. The header is not in Bearer <token> form, or
the token is ≤ 10 characters.
Verify. Re-issue with a literal Authorization: Bearer
$YOUR_LONG_KEY header. If your token is short, the v1.0.0
implementation will reject it.
Safe remediation. Use a longer key (32+ characters recommended). The operator runbook explains how to rotate a key.
Escalate if. A long, well-formed key still produces 401. The
gateway may have a startup failure that prevents it from accepting
anything. Check /healthz.
"The response model field is deepseek/deepseek-v4-flash-0731 but I asked for Pro."¶
Likely cause. A hard Pro rule fired but the chosen tier was substituted by the model-health filter because Pro was unhealthy. The fallback path may have used GLM-5.2; check the routing metrics.
Verify. Look at the structured logs for Routing decision made
events and at sgw_routing_decisions_total{action="FALLBACK_TRY"}.
If the count is high, Pro is unhealthy.
Safe remediation. None for the client. Wait for Pro to recover via half-open probes, or escalate to the operator.
"I get 500 with 'OpenRouter API error: 401'."¶
Likely cause. The server-side OpenRouter key is bad. This is a deployment issue.
Verify. Run docker exec smart-supervisor-production-gateway-1
env | grep OPENROUTER_API_KEY on the host (if you have access).
The key should be set.
Safe remediation. None for the client. The operator must investigate; if you are the operator, rotate the OpenRouter key.
"The /healthz endpoint returns 200 but no requests succeed."¶
Likely cause. The FastAPI process is alive but something in the
request pipeline is broken. Common: PostgreSQL is unreachable and
the gateway entered SAFE_DEGRADED.
Verify. Look at the structured logs for
DegradedModeError or STOP_FOR_HUMAN. Look at
sgw_requests_total{status="500"} for the spike.
Safe remediation. None for the client. The operator must investigate.
"The streaming response just stops mid-sentence."¶
Likely cause. The client closed the connection, or
nginx's proxy_read_timeout (300s) elapsed. The gateway does not
have a separate streaming timeout in v1.0.0.
Verify. Look at the structured logs for a successful
status="200" event with the same task ID. If the metric is
recorded, the gateway believes the response completed; if the
client disagrees, the issue is on the client side.
Safe remediation. Check your client's network stability. If the issue happens consistently, file a bug.
"I get 422 'ensure greater than or equal to 0' on max_tokens."¶
Likely cause. You sent a negative max_tokens. Pydantic
rejects negative values.
Verify. The error detail lists the offending field.
Safe remediation. Send a non-negative integer.
"I cannot find a route to /v1/models."¶
The gateway does not implement /v1/models in v1.0.0. There is
no list endpoint for the model registry. See
API reference → Overview.
If you need to enumerate models, query OpenRouter directly at
https://openrouter.ai/api/v1/models with your OpenRouter key.
"I get rate-limited by OpenRouter."¶
Likely cause. OpenRouter rate limits are propagated as 429 responses after the gateway's internal retries exhaust.
Verify. Look at the structured logs for
"message": "OpenRouter API failed after retries with status 429".
Safe remediation. Back off, retry later. Reduce request rate on the client.