Skip to content

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.

See User guide → Streaming.

"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.

See also