{"record":{"id":"890ed6936fabbbcb","repo":"Hmbown/CodeWhale","slug":"compactruntimeerror-response-status-body-index","errorCode":null,"errorMessage":"${compactRuntimeError(response.status, body)}","messagePattern":"\\$\\{compactRuntimeError\\(response\\.status, body\\)\\}","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"integrations/feishu-bridge/src/index.mjs","lineNumber":333,"sourceCode":"\nasync function streamTurnEvents(chatId, threadId, turnId, sinceSeq) {\n  const controller = new AbortController();\n  const timeout = setTimeout(() => controller.abort(), config.turnTimeoutMs);\n  let responseText = \"\";\n  let latestSeq = sinceSeq;\n  let sentProgressAt = Date.now();\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      const record = JSON.parse(event.data);\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 || \"\";\n        const now = Date.now();\n        if (responseText.length > config.maxReplyChars && now - sentProgressAt > 15000) {\n          await sendText(chatId, responseText.slice(0, config.maxReplyChars));\n          responseText = responseText.slice(config.maxReplyChars);\n          sentProgressAt = now;\n        }","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/integrations/feishu-bridge/src/index.mjs#L315-L351","documentation":"streamTurnEvents in the Feishu bridge throws when the HTTP response that should carry the Server-Sent-Events turn stream has a non-OK status. The body is read with readJsonSafe and formatted via compactRuntimeError, so the message carries the Runtime's status and error payload.","triggerScenarios":"Calling streamTurnEvents when the Runtime rejects the turn-streaming request — 401 from stale auth headers, 404 from a wrong RUNTIME_URL path, 400 from an invalid turn payload, or 5xx from a Runtime crash.","commonSituations":"Feishu bridge env credentials out of sync with the running Runtime after a restart; wrong base URL/port in the bridge env; Runtime rejecting a malformed conversation/turn id built from a Feishu message.","solutions":["Check the status and body in the thrown message: fix auth (re-derive tokens), URL, or payload accordingly.","Verify the bridge's runtime base URL and auth env vars match the currently running `codewhale web` instance.","Inspect Runtime logs for the 5xx cause if the status is a server error, and check the turn request body for malformed ids."],"exampleFix":"// before: stale session headers after Runtime restart\nheaders: authHeaders()\n// after: restart bridge alongside the Runtime so credentials regenerate\n// $ codewhale web && npm run start --prefix integrations/feishu-bridge","handlingStrategy":"try-catch","validationCode":"const res = await fetch(streamUrl, { method: 'POST', headers: authHeaders() });\nif (!res.ok) throw new Error(await res.text());\nif (!res.headers.get('content-type')?.includes('text/event-stream')) throw new Error('not an SSE stream');","typeGuard":"function isRuntimeHttpError(err) {\n  return err instanceof Error && /\\b\\d{3}\\b/.test(err.message);\n}","tryCatchPattern":"try {\n  await streamTurnEvents(payload);\n} catch (e) {\n  console.error('[feishu] turn stream failed:', e.message);\n  await replyToFeishu('Backend error: ' + e.message.slice(0, 200));\n}","preventionTips":["Restart the bridge whenever the Runtime restarts so auth tokens and base URL stay in sync.","Verify the runtime URL with a lightweight GET before opening SSE streams.","Validate turn payload fields (conversation/turn ids) before sending."],"tags":["http","sse","streaming","feishu-bridge","runtime"],"backgroundTag":"http-error-response","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}