{"record":{"id":"411b34d90dc161e8","repo":"vercel/ai","slug":"no-finish-chunk-received","errorCode":null,"errorMessage":"No finish chunk received","messagePattern":"No finish chunk received","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/workflow/src/workflow-chat-transport.ts","lineNumber":537,"sourceCode":"        if (consecutiveErrors >= this.maxConsecutiveErrors) {\n          throw new Error(\n            `Failed to reconnect after ${this.maxConsecutiveErrors} consecutive errors. Last error: ${getErrorMessage(error)}`,\n          );\n        }\n      }\n    }\n\n    await this.onFinish(gotFinish, { chatId: options.chatId, chunkIndex });\n  }\n\n  private async onFinish(\n    gotFinish: boolean,\n    { chatId, chunkIndex }: { chatId: string; chunkIndex: number },\n  ) {\n    if (gotFinish) {\n      await this.onChatEnd?.({ chatId, chunkIndex });\n    } else {\n      throw new Error('No finish chunk received');\n    }\n  }\n}\n","sourceCodeStart":519,"sourceCodeEnd":541,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/workflow/src/workflow-chat-transport.ts#L519-L541","documentation":"After the reconnect loop ends, onFinish checks whether a 'finish' chunk was observed in the stream. If the stream ended (or all attempts exhausted) without a finish chunk, onChatEnd is skipped and this error is thrown, because the chat transcript is incomplete.","triggerScenarios":"The reconnected stream terminates without ever yielding a type==='finish' chunk — server closed the stream early, reconnect attempts exhausted while loop condition ended, or the stream was truncated.","commonSituations":"Server crash or deployment restart mid-run; long-running agent killed before completion; orphan chunk filtering dropping the finish chunk; network close before final chunk.","solutions":["Check server logs for why the workflow stream ended before emitting a finish chunk.","Handle this error client-side by treating the chat as incomplete and reconnecting/sending again.","Ensure the server always emits a finish chunk even on workflow failure.","Check orphanFilter logic isn't dropping the finish chunk."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// server-side: guarantee finish emission\ntry { await runWorkflow(); } finally { writer.write({ type: 'finish' }); }","typeGuard":null,"tryCatchPattern":"try {\n  await transport.reconnectToStream({ chatId });\n} catch (e) {\n  if (e instanceof Error && e.message === 'No finish chunk received') {\n    // mark chat as incomplete in UI and offer resend/reconnect\n  } else throw e;\n}","preventionTips":["Server should always emit a finish chunk, even on workflow error.","Keep onChatEnd logic resilient: treat missing finish as an incomplete run event.","Review orphanFilter rules so they can't drop the finish chunk.","Alert on server-side stream terminations without finish."],"tags":["streaming","workflow","incomplete"],"backgroundTag":"stream-ended-without-finish","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}