vercel/ai · error · Error
.append(): The current value is not a string. Received: ${ty
Error message
.append(): The current value is not a string. Received: ${typeof currentValue} What it means
append() only works on streamable values whose current value is a string (or undefined for a fresh value). If the value has been set to any other type via update() or the initial value, this error is thrown, reporting the actual typeof the current value.
Source
Thrown at packages/rsc/src/streamable-value/create-streamable-value.ts:229
const resolvePrevious = resolvable.resolve;
resolvable = createResolvablePromise();
updateValueStates(value);
currentPromise = resolvable.promise;
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;View on GitHub (pinned to 69428b1f8b)
Solutions
- Use append() exclusively from the start on a createStreamableValue() with no initial (or a string initial) value
- Use update() instead of append() if you intend to replace the value with non-string data
- Use separate streamable values: one for streamed text (append), one for structured data (update)
- Reset the value to a string with update('') before appending
Example fix
// before
const v = createStreamableValue({ count: 0 });
v.append('hi'); // throws
// after
const v = createStreamableValue('');
v.append('hi'); Defensive patterns
Strategy: validation
Validate before calling
function safeAppend(streamable, current, chunk) {
if (typeof current !== 'string' && typeof current !== 'undefined') {
throw new TypeError('append requires a string-valued streamable, got: ' + typeof current);
}
streamable.append(chunk);
} Type guard
function canAppendTo(value) {
return typeof value === 'string' || typeof value === 'undefined';
} Try / catch
try {
streamable.append(chunk);
} catch (e) {
if (!/current value is not a string/.test(String(e.message))) throw e;
streamable.update(String(chunk)); // fall back to replace-mode
} Prevention
- Never mix update() with non-string values and append() on the same streamable
- Create append-style streams with createStreamableValue() and no initial object
- Keep a convention: one streamable per value type (text vs structured)
When it happens
Trigger: Creating createStreamableValue({someObject}) or calling .update({...}) / .update(42), then calling .append('text') — the current value is no longer a string.
Common situations: Mixing text-streaming append() with whole-value update() on the same streamable; initializing a streamable with a non-string value intending to append to it later.
Related errors
- .append(): The value is not a string. Received: ${typeof val
- ${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/92fd374d975c8435.
Report an issue: GitHub.