{"record":{"id":"13fdc94cd084906b","repo":"vercel/ai","slug":"workflowchattransport-negative-initialstartindex","errorCode":null,"errorMessage":"[WorkflowChatTransport] Negative initialStartIndex is configured (${explicitStartIndex}) but the reconnection endpoint did not return a valid \"x-workflow-stream-tail-index\" header. Retries will replay the stream from the beginning. See: https://workflow.dev/docs/ai/resumable-streams#resuming-from-the-end-of-the-stream","messagePattern":"\\[WorkflowChatTransport\\] Negative initialStartIndex is configured \\((.+?)\\) but the reconnection endpoint did not return a valid \"x-workflow-stream-tail-index\" header\\. Retries will replay the stream from the beginning\\. See: https://workflow\\.dev/docs/ai/resumable-streams#resuming-from-the-end-of-the-stream","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/workflow/src/workflow-chat-transport.ts","lineNumber":481,"sourceCode":"      if (useExplicitStartIndex && explicitStartIndex > 0) {\n        // Positive startIndex: the first request starts at this absolute\n        // position, so set chunkIndex to match so subsequent retries\n        // resume from (explicitStartIndex + chunks received).\n        chunkIndex = explicitStartIndex;\n      } else if (useExplicitStartIndex && explicitStartIndex < 0) {\n        const tailIndexHeader = response.headers.get(\n          'x-workflow-stream-tail-index',\n        );\n        const tailIndex =\n          tailIndexHeader !== null ? parseInt(tailIndexHeader, 10) : NaN;\n\n        if (!Number.isNaN(tailIndex)) {\n          // Resolve: e.g. tailIndex=499, startIndex=-20 → 500 + (-20) = 480\n          chunkIndex = Math.max(0, tailIndex + 1 + explicitStartIndex);\n        } else {\n          // Header missing or unparseable — fall back to replaying from the\n          // beginning so retries don't resume from a wrong position.\n          console.warn(\n            '[WorkflowChatTransport] Negative initialStartIndex is configured ' +\n              `(${explicitStartIndex}) but the reconnection endpoint did not ` +\n              'return a valid \"x-workflow-stream-tail-index\" header. Retries ' +\n              'will replay the stream from the beginning. See: ' +\n              'https://workflow.dev/docs/ai/resumable-streams#resuming-from-the-end-of-the-stream',\n          );\n          replayFromStart = true;\n        }\n      }\n      useExplicitStartIndex = false;\n\n      try {\n        const chunkStream = parseJsonEventStream({\n          stream: response.body,\n          schema: uiMessageChunkSchema,\n        });\n        for await (const chunk of createAsyncIterableStream(chunkStream)) {\n          if (!chunk.success) {","sourceCodeStart":463,"sourceCodeEnd":499,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/workflow/src/workflow-chat-transport.ts#L463-L499","documentation":"A negative initialStartIndex means 'resume N chunks from the end of the stream', which requires the reconnection endpoint to report the total chunk count via the 'x-workflow-stream-tail-index' header. When that header is missing or unparseable, the transport cannot compute the offset and warns that retries will replay the whole stream from the beginning instead.","triggerScenarios":"Configuring WorkflowChatTransport with a negative initialStartIndex while the reconnect endpoint's response lacks a valid numeric 'x-workflow-stream-tail-index' header (header absent, non-numeric, or NaN).","commonSituations":"Custom reconnection endpoints that don't implement the tail-index header; proxies stripping custom headers; older server versions predating the header.","solutions":["Make the reconnection endpoint return the 'x-workflow-stream-tail-index' header with the last chunk index.","Check that no proxy/middleware strips the custom header from reconnection responses.","Use a non-negative initialStartIndex (absolute chunk position) instead of relative-from-end semantics.","Accept full replay on retries if streams are idempotent for your app."],"exampleFix":"// server: reconnection endpoint\nres.setHeader('x-workflow-stream-tail-index', String(lastChunkIndex));","handlingStrategy":"validation","validationCode":"// client-side preflight\nconst res = await fetch(reconnectUrl, { method: 'HEAD' });\nif (initialStartIndex < 0 && !res.headers.get('x-workflow-stream-tail-index')) {\n  console.warn('Reconnect endpoint lacks tail-index header; full replay will occur.');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Implement the x-workflow-stream-tail-index header on reconnection endpoints","Verify custom headers survive proxies and CDNs","Prefer absolute startIndex when the header cannot be provided"],"tags":["streaming","resume","headers","workflow"],"backgroundTag":"missing-stream-tail-header","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}