Hmbown/CodeWhale · error
${compactRuntimeError(response.status, body)}
Error message
${compactRuntimeError(response.status, body)} What it means
The Weixin bridge's streamTurnEvents throws compactRuntimeError(response.status, body) when the SSE endpoint responds with a non-OK status, before consuming any events. The error carries the HTTP status and any error details from the JSON body, turning runtime-side rejections into an explicit failure instead of an empty or broken event stream.
Solutions
- Address the status shown in the message: fix auth for 401/403, fix runtimeUrl for 404, back off for 429, check runtime logs for 5xx.
- Confirm the runtime service is running and reachable at the configured address.
- Update the token/secret used by authHeaders().
Example fix
// before WEIXIN_BRIDGE_RUNTIME_URL=http://localhost:7000 # runtime on 8080 // Error: 404 ... // after WEIXIN_BRIDGE_RUNTIME_URL=http://localhost:8080
Defensive patterns
Strategy: retry
Validate before calling
const base = process.env.WEIXIN_BRIDGE_RUNTIME_URL;
const res = await fetch(`${base}/health`);
if (!res.ok) throw new Error(`Runtime not ready: HTTP ${res.status}`); Try / catch
async function streamWithRetry(input, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try {
for await (const event of streamTurnEvents(input)) handle(event);
return;
} catch (err) {
if (/^(429|5\d\d)/.test(err.message) && i < attempts - 1) {
await delay(1000 * 2 ** i);
continue;
}
throw err;
}
}
} Prevention
- Health-check the runtime before opening SSE connections.
- Use exponential backoff for 429/5xx instead of tight reconnect loops.
- Rotate auth tokens before expiry so streams are not rejected mid-operation.
- Confirm the runtime URL/port in configuration matches the deployed runtime.
When it happens
Trigger: fetch of the turn-events SSE endpoint resolves with response.ok false: 401/403 (bad auth headers), 404 (wrong runtimeUrl or path), 429 (rate limiting), or 5xx (runtime fault).
Common situations: Wrong port/host in runtime configuration, expired credentials, runtime restart invalidating tokens, or a proxy/load balancer returning 502/503 while the runtime is down.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- ${compactRuntimeError(response.status, body)}
- ${compactRuntimeError(response.status, body)}
- ${compactRuntimeError(response.status, body)}
- ${compactRuntimeError(response.status, result)}
- Stream read error
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/729a40b4df71b433.
Report an issue: GitHub.
Appendix: source
Thrown at integrations/weixin-bridge/src/index.mjs:420
const timeout = setTimeout(
() => controller.abort(),
config.turnTimeoutMs
);
let responseText = "";
let latestSeq = sinceSeq;
let sentProgressAt = Date.now();
try {
const response = await fetch(
`${config.runtimeUrl}/v1/threads/${encodeURIComponent(threadId)}/events?since_seq=${sinceSeq}`,
{
headers: authHeaders(),
signal: controller.signal,
}
);
if (!response.ok) {
const body = await readJsonSafe(response);
throw new Error(compactRuntimeError(response.status, body));
}
for await (const event of readSse(response)) {
if (!event.data) continue;
const record = JSON.parse(event.data);
latestSeq = Math.max(latestSeq, Number(record.seq || 0));
await threadStore.patchChat(chatId, { lastSeq: latestSeq });
if (turnId && record.turn_id && record.turn_id !== turnId) continue;
if (
record.event === "item.delta" &&
record.payload?.kind === "agent_message"
) {
responseText += record.payload.delta || "";
const now = Date.now();
if (
responseText.length > config.maxReplyChars &&View on GitHub (pinned to 433685b202)