Hmbown/CodeWhale · error · Error
DeepSeek ${res.status}: ${text}
Error message
DeepSeek ${res.status}: ${text} What it means
web/lib/deepseek.ts drives the 'Today's Dispatch' digest editor; when the DeepSeek chat API answers non-2xx it throws `DeepSeek <status>: <body text>` so Workers logs carry the upstream error verbatim (temperature 0.4, max_tokens 4096, optional json_object mode).
Source
Thrown at web/lib/deepseek.ts:45
const model = dsEnv?.model ?? process.env.DEEPSEEK_MODEL ?? FALLBACK_MODEL;
const res = await fetch(`${base}/v1/chat/completions`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify({
model,
messages,
temperature: 0.4,
max_tokens: 4096,
reasoning_effort: "high",
...(jsonMode ? { response_format: { type: "json_object" } } : {}),
}),
});
if (!res.ok) {
const text = await res.text();
throw new Error(`DeepSeek ${res.status}: ${text}`);
}
const data = (await res.json()) as ChatResponse;
return data.choices[0]?.message?.content ?? "";
}
const SYSTEM_PROMPT = `You are the editor of "今日要闻 / Today's Dispatch", a daily-ish digest for the Codewhale open source project.
You receive: repo stats and a list of recently updated issues, PRs, and releases.
Output a single JSON object — no prose around it — matching this exact shape:
{
"headline": "string — English editorial headline (max ~70 chars)",
"summary": "string — 2-3 English sentences, calm factual editorial voice",
"highlights": [
{ "title": "string", "href": "string", "tag": "shipped|merged|opened|discussion|release", "blurb": "one sentence, max ~120 chars" }
],
"movers": [
{ "number": 123, "title": "string", "href": "string", "reason": "one short clause" }View on GitHub (pinned to 8880682c63)
Solutions
- Set/rotate DEEPSEEK_API_KEY (wrangler secret put DEEPSEEK_API_KEY) and redeploy
- Check the DeepSeek console balance for 402
- Wrap the digest call in exponential backoff for 429/5xx
- Confirm the model env value exists on api.deepseek.com
Example fix
// before
if (!res.ok) {
const text = await res.text();
throw new Error(`DeepSeek ${res.status}: ${text}`);
}
// after - classify and retry transient failures
if (res.status === 429 || res.status >= 500) {
await sleep(1000 * 2 ** attempt);
continue;
}
if (!res.ok) {
const text = await res.text();
throw new Error(`DeepSeek ${res.status}: ${text}`);
} Defensive patterns
Strategy: retry
Validate before calling
const apiKey = (env.DEEPSEEK_API_KEY || '').trim();
if (!apiKey) {
return new Response('dispatch generator is not configured (missing DEEPSEEK_API_KEY)', { status: 503 });
} Try / catch
catch (err) {
const m = /^DeepSeek (\d+):/.exec(String(err.message));
if (m && (m[1] === '429' || Number(m[1]) >= 500)) {
ctx.waitUntil(scheduleRetryIn(60)); // back off and retry the digest later
return;
}
console.error('dispatch generation failed:', err.message);
} Prevention
- Set secrets via wrangler and verify with wrangler secret list before relying on the cron
- Retry digests idempotently - regeneration should be safe to repeat
- Alert on repeated 401/402 so key/balance issues surface quickly
When it happens
Trigger: generateDispatch calls with a missing/invalid DEEPSEEK_API_KEY (401), exhausted credits (402), rate limiting (429), an unknown model id (400), or DeepSeek 5xx during digest generation.
Common situations: Secret not set on the deployed Workers environment; expired key; the digest cron firing repeatedly into 429; the configured model drifting from DeepSeek's catalog.
Related errors
- DeepSeek ${res.status}: ${text}
- FIM API error: HTTP {status}: {error_text}
- FIM response missing choices[0].text
- Failed to call DeepSeek Chat API: HTTP {status}: {error_text
- expected application/x-www-form-urlencoded
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/ed7531cd70590b7b.
Report an issue: GitHub.