vercel/ai · error
Invalid patch: can only append to string types. This is a bu
Error message
Invalid patch: can only append to string types. This is a bug in the AI SDK.
What it means
Streamable values support delta patches only for string payloads. While replaying a diff with type 0 (append), the accumulated value must be a string; if it is not, the SDK throws and explicitly labels it an internal bug, since a text patch should never be applied to a non-string value.
Source
Thrown at packages/rsc/src/streamable-value/read-streamable-value.tsx:70
async next() {
// the iteration is done already, return the last value:
if (isDone) return { value, done: true };
// resolve the promise at the beginning of each iteration:
row = await row;
// throw error if any:
if (row.error !== undefined) {
throw row.error;
}
// if there is a value or a patch, use it:
if ('curr' in row || row.diff) {
if (row.diff) {
// streamable patch (text only):
if (row.diff[0] === 0) {
if (typeof value !== 'string') {
throw new Error(
'Invalid patch: can only append to string types. This is a bug in the AI SDK.',
);
}
// casting required to remove T & string limitation
(value as string) = value + row.diff[1];
}
} else {
// replace the value (full new value)
value = row.curr;
}
// The last emitted { done: true } won't be used as the value
// by the for await...of syntax.
if (!row.next) {
isDone = true;
return { value, done: false };
}View on GitHub (pinned to 69428b1f8b)
Solutions
- Upgrade @ai-sdk/rsc / ai to the same latest version on both server and client
- Ensure the server never applies string patches after changing the underlying value to a non-string
- Report the bug to the AI SDK repository if it reproduces on a single consistent version, including the value shape
Example fix
// before (server)
value.update({ done: true }); // non-string after text patches
value.append('more text');
// after
value.update('final string content'); // keep string-only when using append/patches Defensive patterns
Strategy: try-catch
Validate before calling
// client-side sanity check before consuming diffs
if (typeof initial !== 'string' && usesAppendPatch) throw new Error('string patches require string values'); Try / catch
try {
for await (const text of readStreamableValue(streamable)) { /* ... */ }
} catch (e) {
if (e instanceof Error && e.message.includes('Invalid patch')) {
console.error('SDK patching bug: report with value shape and versions');
return;
}
throw e;
} Prevention
- Do not change a streamable value's type from string to object mid-stream
- Keep server and client AI SDK versions in sync
- Upgrade to the latest version before reporting; this error signals an internal bug
When it happens
Trigger: A client receiving a diff-encoded StreamableValue whose base `curr` is not a string while a text patch arrives — typically caused by server-side state corruption: applying patches after the value type changed, or a version mismatch producing incompatible patch encoding.
Common situations: Server code that switches a streamable value from string to object mid-stream and keeps diffing; mixed AI SDK versions between RSC server and client bundle; custom transport that reorders or merges patches incorrectly.
Related errors
- 'element streams in no-schema mode' functionality not suppor
- 'element streams in object mode' functionality not supported
- Unsupported chunk type: ${_exhaustiveCheck}
- 'element streams in enum mode' functionality not supported.
- Unsupported chunk type: ${_exhaustiveCheck}
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/dd813458ff8ba3f0.
Report an issue: GitHub.