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

  1. Set/rotate DEEPSEEK_API_KEY (wrangler secret put DEEPSEEK_API_KEY) and redeploy
  2. Check the DeepSeek console balance for 402
  3. Wrap the digest call in exponential backoff for 429/5xx
  4. 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

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


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/ed7531cd70590b7b. Report an issue: GitHub.