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

  1. Upgrade @ai-sdk/rsc / ai to the same latest version on both server and client
  2. Ensure the server never applies string patches after changing the underlying value to a non-string
  3. 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

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


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/dd813458ff8ba3f0. Report an issue: GitHub.