vercel/ai · error
Chunking function must return a non-empty string.
Error message
Chunking function must return a non-empty string.
What it means
Plain Error thrown by smoothStream when a custom ChunkDetector function returns an empty string ('' or zero-length match). A chunker must either return null (nothing to flush yet) or a non-empty prefix of the buffer; an empty return is treated as a programming bug in the detector.
Source
Thrown at packages/ai/src/generate-text/smooth-stream.ts:71
typeof chunking.segment === 'function'
) {
const segmenter = chunking as Intl.Segmenter;
detectChunk = (buffer: string) => {
if (buffer.length === 0) return null;
const iterator = segmenter.segment(buffer)[Symbol.iterator]();
const first = iterator.next().value;
return first?.segment || null;
};
} else if (typeof chunking === 'function') {
detectChunk = buffer => {
const match = chunking(buffer);
if (match == null) {
return null;
}
if (!match.length) {
throw new Error(`Chunking function must return a non-empty string.`);
}
if (!buffer.startsWith(match)) {
throw new Error(
`Chunking function must return a match that is a prefix of the buffer. Received: "${match}" expected to start with "${buffer}"`,
);
}
return match;
};
} else {
const chunkingRegex =
typeof chunking === 'string'
? CHUNKING_REGEXPS[chunking]
: chunking instanceof RegExp
? chunking
: undefined;
View on GitHub (pinned to 69428b1f8b)
Solutions
- Return `null` instead of an empty string when no chunk should be emitted yet.
- Check the detector for paths that can compute a zero-length slice; guard with `if (idx <= 0) return null;`.
- Test the detector against edge inputs: '', ' ', first partial token, multi-byte characters.
Example fix
// before
const chunking = (buffer: string) => buffer.slice(0, buffer.indexOf(' ') + 1); // '' when no space
// after
const chunking = (buffer: string) => {
const idx = buffer.indexOf(' ');
return idx === -1 || idx + 1 === 0 ? null : buffer.slice(0, idx + 1);
}; Defensive patterns
Strategy: validation
Validate before calling
const detector = (buffer: string) => {
const chunk = computeChunk(buffer);
if (chunk != null && chunk.length === 0) return null; // never return ''
return chunk;
}; Type guard
function isValidDetectorResult(r: string | null): r is string {
return r === null || r.length > 0;
} Try / catch
try {
result.textStream.pipeThrough(smoothStream({ chunking: detector }).pipeThrough(new TextEncoderStream()));
} catch (e) {
if (e instanceof Error && e.message.includes('non-empty string')) {
// fall back to default word chunking
} else throw e;
} Prevention
- Return null, never '', from custom detectors when no chunk is ready.
- Unit-test detectors with empty, single-char, and whitespace-only buffers.
- Avoid slice expressions that can yield length 0 (guard the index).
When it happens
Trigger: Passing `chunking: (buffer) => ...` that returns '' — e.g. slicing with an index computed as 0, regex with optional capture yielding empty, or returning `match?.[0] ?? ''` instead of null.
Common situations: Custom detectors written with `buffer.slice(0, n)` where n=0 on first token; using `match[1]` from a regex whose capture group didn't participate; returning empty on whitespace-only buffers.
Related errors
- Chunking function must return a match that is a prefix of th
- Chunking must be "word", "line", a RegExp, an Intl.Segmenter
- Chunking RegExp must not match an empty string.
- 'element streams in no-schema mode' functionality not suppor
- 'element streams in object mode' functionality not supported
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/1085c5253fd1537a.
Report an issue: GitHub.