mastra-ai/mastra · error · TypeError

The chunking function must return a prefix of the buffered t

Error message

The chunking function must return a prefix of the buffered text.

What it means

createChunkDetector wraps a custom chunking function for smoothStream and verifies that any returned match is a prefix of the current text buffer. The smoothing machinery only consumes text from the front of the buffer; a match that is not a prefix could never be flushed in order, so the library throws a TypeError instead of corrupting or reordering the output stream.

Source

Thrown at packages/core/src/stream/smooth-stream.ts:67

      const firstSegment = chunking.segment(buffer)[Symbol.iterator]().next().value;
      return firstSegment?.segment || null;
    };
  }

  if (typeof chunking === 'function') {
    return buffer => {
      const match = chunking(buffer);

      if (match == null) {
        return null;
      }

      if (!match.length) {
        throw new TypeError('The chunking function must return a non-empty string.');
      }

      if (!buffer.startsWith(match)) {
        throw new TypeError('The chunking function must return a prefix of the buffered text.');
      }

      return match;
    };
  }

  const pattern = typeof chunking === 'string' ? CHUNKING_PATTERNS[chunking] : chunking;

  if (!(pattern instanceof RegExp)) {
    throw new TypeError('chunking must be "word", "line", a RegExp, an Intl.Segmenter, or a chunk detector function.');
  }

  return buffer => {
    pattern.lastIndex = 0;
    const match = pattern.exec(buffer);

    if (!match) {
      return null;

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Return buffer.slice(0, boundaryIndex) — always cut from the start of the buffer.
  2. If the boundary is mid-buffer, either return the leading portion up to that boundary, or return null and let the buffer grow until the boundary reaches the front.
  3. Never transform or re-case the returned text; return the exact leading substring of the buffer.

Example fix

// before
const chunking = buffer => {
  const idx = buffer.indexOf('|');
  return idx === -1 ? null : buffer.slice(0, idx + 1).trim(); // trim may break prefix property
};

// after
const chunking = buffer => {
  const idx = buffer.indexOf('|');
  return idx === -1 ? null : buffer.slice(0, idx + 1);
};
Defensive patterns

Strategy: validation

Validate before calling

function isPrefixChunker(fn: (buf: string) => string | null): boolean {
  const buf = 'hello world';
  const out = fn(buf);
  return out === null || buf.startsWith(out);
}

Type guard

function isBufferPrefix(out: string | null, buffer: string): out is string {
  return out !== null && buffer.startsWith(out);
}

Try / catch

try {
  streamText({ model, smoothStream: { chunking: myChunker } });
} catch (err) {
  if (err instanceof TypeError && err.message.includes('prefix of the buffered text')) {
    console.error('chunker must return buffer.slice(0, n) — never interior or transformed text');
  } else throw err;
}

Prevention

When it happens

Trigger: Calling smoothStream({ chunking: myFn }) where myFn(buffer) returns text that does not appear at position 0 of the buffer — e.g. returning buffer.slice(5, 10), returning a matched segment found mid-buffer, or returning a transformed/normalized version of the text.

Common situations: Custom detectors that search the whole buffer and return an interior match; detectors that return text after applying case/format transformations; reusing a detector designed for a different buffering scheme.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/291fd688a1c1ee0f. Report an issue: GitHub.