{"record":{"id":"aea7d17e08a24571","repo":"Hmbown/CodeWhale","slug":"runtime-api-request-failed-status-message-aea7d1","errorCode":null,"errorMessage":"Runtime API request failed (${status}): ${message}","messagePattern":"Runtime API request failed \\((.+?)\\): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"integrations/wecom-bridge/src/index.mjs","lineNumber":317,"sourceCode":"\nasync function streamTurnEvents(chatId, frame, threadId, turnId, sinceSeq) {\n  const controller = new AbortController();\n  const timeout = setTimeout(() => controller.abort(), config.turnTimeoutMs);\n  const streamId = generateReqId(\"stream\");\n  let responseText = \"\";\n  let latestSeq = sinceSeq;\n\n  try {\n    const response = await fetch(\n      `${config.runtimeUrl}/v1/threads/${encodeURIComponent(threadId)}/events?since_seq=${sinceSeq}`,\n      {\n        headers: authHeaders(),\n        signal: controller.signal\n      }\n    );\n    if (!response.ok) {\n      const body = await readJsonSafe(response);\n      throw new Error(compactRuntimeError(response.status, body));\n    }\n\n    for await (const event of readSse(response)) {\n      if (!event.data) continue;\n      let record;\n      try {\n        record = JSON.parse(event.data);\n      } catch (error) {\n        console.warn(\"Skipping malformed runtime SSE event:\", publicBridgeError(error));\n        continue;\n      }\n      latestSeq = Math.max(latestSeq, Number(record.seq || 0));\n      await threadStore.patchChat(chatId, { lastSeq: latestSeq });\n\n      if (turnId && record.turn_id && record.turn_id !== turnId) continue;\n\n      if (record.event === \"item.delta\" && record.payload?.kind === \"agent_message\") {\n        responseText += record.payload.delta || \"\";","sourceCodeStart":299,"sourceCodeEnd":335,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/integrations/wecom-bridge/src/index.mjs#L299-L335","documentation":"The WeCom bridge's event pump fetches `${config.runtimeUrl}/v1/threads/{threadId}/events?since_seq=`; a non-ok response is parsed with readJsonSafe and rethrown via compactRuntimeError as `Runtime API request failed (${status}): ${message}`. Malformed SSE records inside an otherwise-200 stream are only logged and skipped, so this throw strictly means the HTTP request itself failed. runtimeUrl defaults to CODEWHALE_RUNTIME_URL or http://127.0.0.1:7878 (index.mjs:39) and the token is CODEWHALE_RUNTIME_TOKEN (index.mjs:40).","triggerScenarios":"401 when CODEWHALE_RUNTIME_TOKEN does not match the runtime; 404 for an unknown or pruned threadId; 5xx when the runtime is failing; CODEWHALE_RUNTIME_URL pointing at a stale port or host.","commonSituations":"WeCom callback server started before the runtime is up; token drift between the TUI runtime and the bridge deployment; chat-state threadIds the runtime no longer retains after a restart.","solutions":["Verify the runtime URL is reachable from the WeCom bridge host and matches where the runtime actually listens","Re-export CODEWHALE_RUNTIME_TOKEN with the current runtime token","Confirm the thread exists via GET /v1/threads/{threadId} with the same auth headers; recreate if pruned","Read the text after the status — it is the runtime's own error message and pinpoints the cause"],"exampleFix":"# before: bridge on default port while runtime listens on 7879\n# after\nexport CODEWHALE_RUNTIME_URL=http://127.0.0.1:7879","handlingStrategy":"retry","validationCode":"const probe = await fetch(\n  `${config.runtimeUrl}/v1/threads/${encodeURIComponent(threadId)}`,\n  { headers: authHeaders() }\n);\nif (!probe.ok) {\n  console.error(`runtime preflight failed: ${probe.status}`);\n  process.exit(2);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await streamThreadEvents(threadId, sinceSeq);\n} catch (error) {\n  const status = Number(error.message.match(/Runtime API request failed \\((\\d+)\\)/)?.[1]);\n  if (status >= 500) { await backoffAndRetry(); return; }\n  throw error;\n}","preventionTips":["Start the runtime before the WeCom bridge and health-check it in the unit ordering","Keep bridge and runtime tokens in one shared secret so they rotate together","Persist lastSeq per chat so stream failures resume instead of replaying"],"tags":["network","api","runtime","sse","wecom-bridge"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}