vercel/ai · error

Chunking RegExp must not match an empty string.

Error message

Chunking RegExp must not match an empty string.

What it means

Error thrown by smoothStream when the chunking RegExp matches an empty string at the current position (zero-length match). Zero-length matches would loop forever producing no progress, so the SDK rejects them.

Source

Thrown at packages/ai/src/generate-text/smooth-stream.ts:113

    }

    detectChunk = buffer => {
      const lastIndex = chunkingRegex.lastIndex;
      chunkingRegex.lastIndex = 0;

      let match: RegExpExecArray | null;
      try {
        match = chunkingRegex.exec(buffer);
      } finally {
        chunkingRegex.lastIndex = lastIndex;
      }

      if (!match) {
        return null;
      }

      if (!match[0].length) {
        throw new Error(`Chunking RegExp must not match an empty string.`);
      }

      return buffer.slice(0, match.index) + match[0];
    };
  }

  return () => {
    let buffer = '';
    let id = '';
    let type: 'text-delta' | 'reasoning-delta' | undefined = undefined;
    let providerMetadata: SharedV4ProviderMetadata | undefined = undefined;

    function flushBuffer(
      controller: TransformStreamDefaultController<TextStreamPart<TOOLS>>,
    ) {
      if (buffer.length > 0 && type !== undefined) {
        controller.enqueue({
          type,

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Replace * with + for consuming classes, e.g. /\s+/ instead of /\s*/.
  2. Anchor the pattern so it must consume at least one character; add an alternation with a required group.
  3. Test the RegExp against typical buffers and assert match[0].length > 0.

Example fix

// before
smoothStream({ chunking: /\s*/ });
// after
smoothStream({ chunking: /\s+/ });
Defensive patterns

Strategy: validation

Validate before calling

if (chunking instanceof RegExp) {
  if (''.match(chunking)?.[0] !== undefined && ''.match(chunking)![0].length === 0) {
    throw new Error('chunking RegExp can match an empty string');
  }
}

Try / catch

try {
  stream(pipeThrough(smoothStream({ chunking: myRegex })));
} catch (e) {
  if (e instanceof Error && e.message.includes('empty string')) {
    // fall back to 'word' chunking
  } else throw e;
}

Prevention

When it happens

Trigger: Passing a RegExp that can match empty input, e.g. /\s*/ (star instead of plus), /(word)?/, or lookahead-only patterns like /(?=\s)/.

Common situations: Using * quantifiers by habit; converting 'line' or 'word' presets to custom regex incorrectly; patterns relying solely on lookaheads without consuming characters.

Related errors


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