DeepSeek API errors fall into four broad groups: authentication, wrong path or model name, rate limiting, and timeouts. The right troubleshooting order is: check the HTTP status code and error type first, then the request ID and a minimal reproduction, and only then change the prompt or the model. Reverse that order and you will easily mistake a configuration problem for a model capability problem.
This article breaks down 401, 404, 429, and timeouts, covering causes, diagnostic steps, and reusable backoff code. Models and prices are listed on the model pricing page.
Note: DeepSeek is a trademark of its owner. Error types, rate-limit policies, and API behavior may change between versions. This article reflects common conditions as of October 2026; the official documentation is authoritative.
1. Distinguish the four error classes first
| Status or symptom | Usual meaning | Typical cause | Order of handling |
|---|---|---|---|
| 401 | Authentication failed | Wrong key, missing Bearer, revoked key | Fix credentials first |
| 404 | Path or model does not exist | Wrong base URL, outdated model name, duplicated path | Check URL and model name |
| 429 | Rate limited or quota constrained | Sudden concurrency spike, shared key, retry storm | Back off, reduce concurrency |
| Timeout | Connect or read timeout | Network, long output, reasoning model, proxy | Diagnose by layer |
| 400 | Bad request parameters or context | Context overflow, malformed format | Quantify, then split |
| 5xx | Upstream service error | Server failure or overload | Back off, switch channel |
Log at least the timestamp, status code, error type, model name, latency, and request ID. Never log a full key, and never print entire user messages into logs.
2. 401: check the header, then the key
A 401 means authentication did not pass; it is usually unrelated to model capability or account balance. Work through this order:
- Is the header using
Authorization: Bearer <key>rather than another auth scheme? - Are there spaces, newlines, or stray quotes around the key? Copying from a chat window is a common source.
- Did the environment variable actually load? Print only the prefix to confirm.
- Has the key been deleted, rotated, or disabled?
- Do the base URL and the key belong to the same platform? An official key sent to a gateway address will return 401.
- Is a reverse proxy overwriting or dropping the
Authorizationheader?
export DEEPSEEK_API_KEY="sk-your-key"
curl "https://api.deepseek.com/chat/completions" \
-H "Authorization: Bearer $DEEPSEEK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-chat",
"messages": [{"role": "user", "content": "Reply with OK only"}],
"max_tokens": 16
}'
If this command returns 200, the key, base URL, and model name are all correct. If it still returns 401, try a new key with a minimal request to separate a key problem from a proxy or gateway configuration problem.
3. 404: the URL and model name are the usual suspects
A 404 usually does not mean "the API is down." It means the request hit a path or model that does not exist. Common causes:
- The base URL points to another vendor, or has an extra or missing
/v1. - The SDK appends
/chat/completionsautomatically, and a hand-written path appends it a second time. - The model name refers to a retired version, or has inconsistent casing or a missing suffix.
- Gateway and official addresses are mixed up, and their path rules differ.
- A reverse proxy rewrite rule corrupts the path.
Start by calling the full URL with curl and reading the error body, then check the base URL and model name against the pricing page. Don't hard-code multiple addresses in code; configure them per environment so a test address never reaches production.
4. 429: rate limiting is not an empty balance
A 429 means the request exceeded rate, concurrency, or quota limits. DeepSeek may throttle or queue requests during peak periods; the official documentation defines the current policy. Common triggers:
- Several services share one key and compete for quota.
- Batch jobs start on the hour at the same time, creating a traffic spike.
- Retries have no backoff, so failures generate more failures and turn into a retry storm.
- Long outputs or reasoning tasks consume more resources, leaving less room for concurrency.
| Symptom | Likely cause | Handling |
|---|---|---|
| 429s cluster at peak hours | Upstream load or traffic spike | Queue, smooth the send rate, shift schedules |
| 429s with one key across services | Shared quota | Split keys by project |
| Worse after retrying | Retries without backoff | Exponential backoff with jitter |
| Long requests hit 429 first | High output-token usage | Lower max_tokens or concurrency |
import random
import time
from openai import OpenAI, RateLimitError, APITimeoutError, APIStatusError
client = OpenAI(
api_key="sk-your-key",
base_url="https://api.deepseek.com",
max_retries=0, # Disable SDK retries so they don't stack with custom retries
)
def ask(prompt: str, retries: int = 4) -> str:
for attempt in range(retries):
try:
resp = client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "user", "content": prompt}],
max_tokens=1024,
timeout=60,
)
return resp.choices[0].message.content
except (RateLimitError, APITimeoutError):
wait = min(2 ** attempt, 20) + random.random()
print(f"Attempt {attempt + 1} failed; waiting {wait:.1f}s")
time.sleep(wait)
except APIStatusError as exc:
if exc.status_code >= 500:
wait = min(2 ** attempt, 20) + random.random()
time.sleep(wait)
continue
raise
raise RuntimeError("Retries exhausted")
print(ask("Explain rate limiting in one sentence"))
Retries only help with transient errors. For operations that already produced side effects, confirm with an idempotency key or a status check before deciding whether to resend.
5. Timeouts: separate connect, read, and streaming
A timeout does not mean the service is unavailable. First locate where the request is stuck:
| Symptom | Likely cause | Handling |
|---|---|---|
| Connect timeout | DNS, network egress, unreachable proxy | Check network and proxy; change route |
| Slow first token | Upstream queueing, prompt too long | Shorten input, shift schedule, use a lighter model |
| Read timeout | Output too long, reasoning model thinking for too long | Raise the read timeout, constrain output |
| Stream interrupted | Network jitter, proxy dropping the stream | Support reconnection, persist what was received |
| Every route times out at once | Local egress or upstream outage | Switch to a backup channel, check status |
import httpx
from openai import OpenAI
client = OpenAI(
api_key="sk-your-key",
base_url="https://api.deepseek.com",
timeout=httpx.Timeout(connect=5.0, read=120.0, write=30.0, pool=10.0),
)
Set connect and read timeouts separately. Setting every timeout to a very large value ties up the thread pool during an outage; setting them too small kills legitimate long tasks. Configure different values by task type.
6. A troubleshooting order to follow
- Record the status code, error type, request ID, model name, and time of occurrence.
- For 401, check the key, headers, environment variables, and platform match.
- For 404, check the base URL, path joining, and model name.
- For 400, check parameters, context length, and image or file formats.
- For 429, check concurrency, shared keys, retry policy, and peak hours.
- For timeouts, check DNS, proxy, output length, and read-timeout settings.
- For 5xx, retry with backoff first; if it persists, contact the provider with the request ID.
- After every incident, add monitoring and alerts instead of waiting for user reports.
7. Monitoring and logging
| Field | Purpose |
|---|---|
| Timestamp and project | Locate peaks and scope of impact |
| Status code and error type | Separate auth, rate-limit, and upstream errors |
| Request ID | Key evidence when asking the provider to investigate |
| Model name and version | Identify problems that appeared after a model change |
| Input and output tokens | Analyze cost and long requests |
| Latency and retry count | Detect tail latency and retry storms |
At minimum, count 401, 404, 429, timeout, and 5xx responses hourly. When the error rate spikes, check whether failures concentrate in one project, one key, or one model before deciding whether to reduce concurrency, switch channels, or roll back a version.
Frequently asked questions
Is a 429 the same as an empty balance?
No. A 429 means the request exceeded rate, concurrency, or quota limits. An insufficient balance usually returns a different error or explains itself in the response body. Check concurrency and shared keys first, then the account balance.
What is the most common cause of a 404?
A wrong base URL, a duplicated path, or an expired model name. Call the full URL with curl, then check the model name against the pricing page; this usually takes only a few minutes.
Should timeouts be retried indefinitely?
No. Retries need a cap, backoff, and alerts. A timeout may also mean the request already executed upstream. For operations with side effects, confirm the state before resending.
What should I do when a streaming response is interrupted?
Record what was received and where the stream stopped, then determine whether the cause was network jitter, a proxy dropping the stream, or an upstream timeout. The client should support reconnection and deduplication; never store a partial response as a complete result.
How do I tell a gateway error from an official error?
Keep the request ID and error type, and send the same request to both the official endpoint and the gateway. This quickly separates key, network, gateway configuration, and upstream service problems.
Next steps
Create a test key on ZSQH AI Gateway, deliberately reproduce a 401, a 404, a 429, and a timeout once each, and then connect production monitoring. Model availability and prices are listed on the model pricing page.
Related reading:
