vercel/ai · error · Error
.append(): The value is not a string. Received: ${typeof val
Error message
.append(): The value is not a string. Received: ${typeof value} What it means
append() validates its argument must be a string since it streams incremental text chunks. Passing a non-string value (number, object, etc.) throws this error reporting the received typeof.
Source
Thrown at packages/rsc/src/streamable-value/create-streamable-value.ts:234
resolvePrevious(createWrapped());
warnUnclosedStream();
return streamable;
},
append(value: T) {
assertStream('.append()');
if (
typeof currentValue !== 'string' &&
typeof currentValue !== 'undefined'
) {
throw new Error(
`.append(): The current value is not a string. Received: ${typeof currentValue}`,
);
}
if (typeof value !== 'string') {
throw new Error(
`.append(): The value is not a string. Received: ${typeof value}`,
);
}
const resolvePrevious = resolvable.resolve;
resolvable = createResolvablePromise();
if (typeof currentValue === 'string') {
currentPatchValue = [0, value];
(currentValue as string) = currentValue + value;
} else {
currentPatchValue = undefined;
currentValue = value;
}
currentPromise = resolvable.promise;
resolvePrevious(createWrapped());
View on GitHub (pinned to 69428b1f8b)
Solutions
- Coerce the chunk to a string before appending (String(chunk) or chunk.toString())
- Use update() if you need to set non-string values
- Add runtime validation on streamed data before appending
- Fix TypeScript types so append is only called with string values
Example fix
// before streamable.append(chunk); // chunk: unknown // after if (typeof chunk === 'string') streamable.append(chunk);
Defensive patterns
Strategy: validation
Validate before calling
function appendText(streamable, chunk) {
if (typeof chunk !== 'string') {
throw new TypeError('append expects string chunks, got: ' + typeof chunk);
}
streamable.append(chunk);
} Type guard
function isStringChunk(chunk) {
return typeof chunk === 'string';
} Try / catch
try {
streamable.append(chunk);
} catch (e) {
if (!/The value is not a string/.test(String(e.message))) throw e;
streamable.append(String(chunk));
} Prevention
- Type stream inputs as string and enable strict TypeScript to catch this at compile time
- Coerce provider deltas (e.g. String(delta)) before appending
- Add a unit test asserting append rejects non-string chunks
When it happens
Trigger: Calling streamable.append(123), .append(someObject), .append(null), or .append(undefined) on a streamable value.
Common situations: Passing non-string LLM token deltas (e.g. parsed objects) to append; assuming append accepts arbitrary values like update does; TS types bypassed with any or untyped data from an API.
Related errors
- .append(): The current value is not a string. Received: ${ty
- ${method}: Value stream is already closed.
- ${method}: Value stream is locked and cannot be updated.
- The streamable value has been slow to update. This may be a
- The streamable UI has been slow to update. This may be a bug
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/bf328b79fbb65c62.
Report an issue: GitHub.