{"record":{"id":"dd813458ff8ba3f0","repo":"vercel/ai","slug":"invalid-patch-can-only-append-to-string-types-th","errorCode":null,"errorMessage":"Invalid patch: can only append to string types. This is a bug in the AI SDK.","messagePattern":"Invalid patch: can only append to string types\\. This is a bug in the AI SDK\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/rsc/src/streamable-value/read-streamable-value.tsx","lineNumber":70,"sourceCode":"        async next() {\n          // the iteration is done already, return the last value:\n          if (isDone) return { value, done: true };\n\n          // resolve the promise at the beginning of each iteration:\n          row = await row;\n\n          // throw error if any:\n          if (row.error !== undefined) {\n            throw row.error;\n          }\n\n          // if there is a value or a patch, use it:\n          if ('curr' in row || row.diff) {\n            if (row.diff) {\n              // streamable patch (text only):\n              if (row.diff[0] === 0) {\n                if (typeof value !== 'string') {\n                  throw new Error(\n                    'Invalid patch: can only append to string types. This is a bug in the AI SDK.',\n                  );\n                }\n\n                // casting required to remove T & string limitation\n                (value as string) = value + row.diff[1];\n              }\n            } else {\n              // replace the value (full new value)\n              value = row.curr;\n            }\n\n            // The last emitted { done: true } won't be used as the value\n            // by the for await...of syntax.\n            if (!row.next) {\n              isDone = true;\n              return { value, done: false };\n            }","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/rsc/src/streamable-value/read-streamable-value.tsx#L52-L88","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before (server)\nvalue.update({ done: true }); // non-string after text patches\nvalue.append('more text');\n// after\nvalue.update('final string content'); // keep string-only when using append/patches","handlingStrategy":"try-catch","validationCode":"// client-side sanity check before consuming diffs\nif (typeof initial !== 'string' && usesAppendPatch) throw new Error('string patches require string values');","typeGuard":null,"tryCatchPattern":"try {\n  for await (const text of readStreamableValue(streamable)) { /* ... */ }\n} catch (e) {\n  if (e instanceof Error && e.message.includes('Invalid patch')) {\n    console.error('SDK patching bug: report with value shape and versions');\n    return;\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["streaming","internal-bug","patching"],"backgroundTag":"invalid-stream-patch","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}