vercel/ai · error

Failed to reconnect after ${this.maxConsecutiveErrors} conse

Error message

Failed to reconnect after ${this.maxConsecutiveErrors} consecutive errors. Last error: ${getErrorMessage(error)}

What it means

During reconnection the transport retries the GET stream request, incrementing a consecutive-error counter each time parsing/connection fails. If it fails maxConsecutiveErrors times in a row, it throws with the count and the last underlying error message. This is a give-up guard against infinite reconnect loops.

Source

Thrown at packages/workflow/src/workflow-chat-transport.ts:520

          chunkIndex++;

          if (orphanFilter?.shouldDrop(chunk.value)) continue;

          yield chunk.value;

          if (chunk.value.type === 'finish') {
            gotFinish = true;
          }
        }
        // Reset consecutive error count only after successful stream parsing
        consecutiveErrors = 0;
      } catch (error) {
        console.error('Error in chat GET reconnectToStream', error);
        consecutiveErrors++;

        if (consecutiveErrors >= this.maxConsecutiveErrors) {
          throw new Error(
            `Failed to reconnect after ${this.maxConsecutiveErrors} consecutive errors. Last error: ${getErrorMessage(error)}`,
          );
        }
      }
    }

    await this.onFinish(gotFinish, { chatId: options.chatId, chunkIndex });
  }

  private async onFinish(
    gotFinish: boolean,
    { chatId, chunkIndex }: { chatId: string; chunkIndex: number },
  ) {
    if (gotFinish) {
      await this.onChatEnd?.({ chatId, chunkIndex });
    } else {
      throw new Error('No finish chunk received');
    }

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Inspect 'Last error' in the message to find the root cause (parse error vs network).
  2. Raise maxConsecutiveErrors or add backoff if the network is merely flaky.
  3. Fix server-side chunk emission so chunks conform to the UI message chunk schema.
  4. Add application-level retry with delay around reconnectToStream.

Example fix

// before
new WorkflowChatTransport({ maxConsecutiveErrors: 3 })
// after
new WorkflowChatTransport({ maxConsecutiveErrors: 10 })
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: ensure reconnect endpoint healthy
const probe = await fetch(reconnectUrl + '?startIndex=0', { headers: authHeaders });
if (!probe.ok) await waitForServer();

Try / catch

try {
  await transport.reconnectToStream({ chatId });
} catch (e) {
  if (e instanceof Error && e.message.includes('consecutive errors')) {
    await new Promise(r => setTimeout(r, backoffMs));
    await transport.reconnectToStream({ chatId }); // outer retry with backoff
  } else throw e;
}

Prevention

When it happens

Trigger: Persistent stream failures during reconnectToStream: repeated malformed chunks (schema parse errors thrown from parseJsonEventStream), repeated network drops, or a server that keeps erroring — reaching maxConsecutiveErrors consecutive failures.

Common situations: Server emitting chunks that fail uiMessageChunkSchema validation; unstable network/proxy dropping connections; server 500-loop on the reconnect endpoint; maxConsecutiveErrors set too low for flaky networks.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/490e2fd29fee5d7e. Report an issue: GitHub.