{"record":{"id":"a24f7f2a552ab446","repo":"coleam00/Archon","slug":"missing-assistant-message","errorCode":"missing_assistant_message","errorMessage":"missing_assistant_message","messagePattern":"missing_assistant_message","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/providers/src/community/pi/event-bridge.ts","lineNumber":162,"sourceCode":"    .filter(b => b.type === 'text')\n    .map(b => b.text ?? '')\n    .join('');\n}\n\n/**\n * Build the terminal `result` chunk from the final `agent_end` event. Pulls\n * usage/stopReason/error from the last assistant message in the returned\n * transcript. When the agent ended in error, surfaces it as `isError: true`.\n */\nexport function buildResultChunk(messages: readonly unknown[]): MessageChunk {\n  const last = [...messages].reverse().find(isAssistantMessage);\n  if (!last) {\n    // agent_end fired with no assistant message in the transcript. This\n    // shouldn't happen in healthy Pi runs — surface it as a loud error\n    // rather than a silent success so orchestrators don't treat a broken\n    // session as a clean completion.\n    getLog().warn('pi.event-bridge.result_missing_assistant_message');\n    return { type: 'result', isError: true, errorSubtype: 'missing_assistant_message' };\n  }\n\n  const tokens = usageToTokens(last.usage);\n  const isError = last.stopReason === 'error' || last.stopReason === 'aborted';\n\n  const chunk: MessageChunk = {\n    type: 'result',\n    tokens,\n    ...(tokens.cost !== undefined ? { cost: tokens.cost } : {}),\n    ...(last.stopReason ? { stopReason: last.stopReason } : {}),\n    ...(typeof last.responseModel === 'string' && last.responseModel.length > 0\n      ? { resolvedModel: { id: last.responseModel } }\n      : {}),\n    ...(isError\n      ? {\n          isError: true,\n          errorSubtype: last.stopReason,\n          // Surfacing errorMessage in errors[] is what makes the executor's","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/providers/src/community/pi/event-bridge.ts#L144-L180","documentation":"buildResultChunk in the Pi event bridge emits a result chunk with isError:true and errorSubtype 'missing_assistant_message' when agent_end fires but the transcript contains no assistant message. Per the source comment this should not happen in healthy Pi runs; the bridge surfaces it loudly (warn log 'pi.event-bridge.result_missing_assistant_message') so orchestrators do not treat a broken session as a clean completion.","triggerScenarios":"A Pi session ends (agent_end) without any assistant message having been bridged: the model produced zero output before termination, the session errored immediately at startup, the run was aborted before the first assistant message, or assistant events were dropped by the transport.","commonSituations":"Pi provider crashed or was killed right after start; auth or network failure so no model call completed; prompt rejected before generation; event stream disconnected mid-run losing the assistant message event; Pi SDK version change altering event ordering.","solutions":["Check the pi.event-bridge.result_missing_assistant_message warn and surrounding Pi session logs for the earliest failure.","Verify Pi provider authentication and connectivity — an immediate upstream failure yields no assistant message.","Re-run the workflow node; a transient transport drop is the usual cause.","If reproducible, run the same prompt through Pi directly to see whether the model emits any events; upgrade the Pi SDK if event ordering changed."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"// before trusting a Pi run result\nconst result = await runPiNode(node);\nif (result.isError && result.errorSubtype === 'missing_assistant_message') {\n  throw new Error('Pi session produced no assistant output — check provider auth/transport, then retry');\n}","typeGuard":"function isMissingAssistantResult(chunk: unknown): chunk is { type: 'result'; isError: true; errorSubtype: 'missing_assistant_message' } {\n  const c = chunk as { type?: string; isError?: boolean; errorSubtype?: string };\n  return c?.type === 'result' && c.isError === true && c.errorSubtype === 'missing_assistant_message';\n}","tryCatchPattern":"for await (const chunk of bridge) {\n  if (isMissingAssistantResult(chunk)) {\n    getLog().warn({}, 'pi_session_completed_without_output');\n    throw new Error('Pi run ended with no assistant message; verify auth/network and retry');\n  }\n}","preventionTips":["Verify Pi provider auth and connectivity before long runs so sessions never start dead.","Treat this result as retryable only after checking for an immediate upstream failure.","Watch pi.event-bridge logs for event-order changes after Pi SDK upgrades.","Keep prompts/limits sane so runs are not aborted before the first assistant message."],"tags":["pi","streaming","session","protocol"],"backgroundTag":"empty-model-response","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}