facebook/react · error · Error

582

582

Error message

Referenced Blob is not a Blob.

What it means

When decoding a client reply, a 'B' row points at a backing entry that was previously uploaded as a real FormData part and is referenced by id. The decoder fetches that entry and requires it to be a Blob/File. If the entry is absent or has been replaced by a string — the classic symptom of re-encoding the FormData through JSON — the instanceof check fails and this error is thrown.

Source

Thrown at packages/react-server/src/ReactFlightReplyServer.js:1886

          DataView,
          1,
          obj,
          key,
          arrayRoot,
        );
      case 'B': {
        // Blob
        const id = parseInt(value.slice(2), 16);
        const prefix = response._prefix;
        const blobKey = prefix + id;
        // We should have this backingEntry in the store already because we emitted
        // it before referencing it. It should be a Blob.
        const backingEntry: Blob = getBackingEntry(
          response._formData,
          blobKey,
        ) as any;
        if (!(backingEntry instanceof Blob)) {
          throw new Error('Referenced Blob is not a Blob.');
        }
        return backingEntry;
      }
      case 'R': {
        return parseReadableStream(response, value, undefined, obj, key);
      }
      case 'r': {
        return parseReadableStream(response, value, 'bytes', obj, key);
      }
      case 'X': {
        return parseAsyncIterable(response, value, false, obj, key);
      }
      case 'x': {
        return parseAsyncIterable(response, value, true, obj, key);
      }
    }
    // We assume that anything else is a reference ID.
    const ref = value.slice(1);

View on GitHub (pinned to eafeac097b)

Solutions

  1. Forward the original request FormData unmodified to decodeReply (or use decodeReplyFromBusboy for multipart streams).
  2. If you must rebuild FormData, append the original File objects — not strings — under their original keys.
  3. Ensure a single Blob/File implementation is in play (pin one undici version, Node >= 20) so the instanceof check succeeds.

Example fix

// before — files flattened to strings
const flat = Object.fromEntries(formData);
const rebuilt = new FormData();
for (const [k, v] of Object.entries(flat)) rebuilt.append(k, v);
const args = await decodeReply(rebuilt);

// after — decode the original FormData
const args = await decodeReply(formData);
Defensive patterns

Strategy: type-guard

Validate before calling

// Verify every expected file entry survived transport as a Blob, cross-realm safe.
export function assertIntactFileEntries(formData: FormData, fileKeys: string[]) {
  for (const key of fileKeys) {
    const v = formData.get(key);
    if (v !== null && !isBlobLike(v)) throw new Error(`entry ${key} is no longer a Blob`);
  }
}

Type guard

// Duck-typed guard: survives cross-realm instances where instanceof Blob fails.
export function isBlobLike(v: unknown): v is Blob {
  if (typeof v !== 'object' || v === null) return false;
  const o = v as any;
  return typeof o.stream === 'function' && typeof o.arrayBuffer === 'function' && typeof o.size === 'number';
}

Try / catch

try {
  const args = await decodeReply(formData);
} catch (e) {
  if (/not a Blob/.test(String((e as Error)?.message))) {
    return badRequest('upload payload corrupted in transit');
  }
  throw e;
}

Prevention

When it happens

Trigger: decodeReply(formData) where the file row references an entry key that is missing or holds a string; rebuilding FormData via Object.fromEntries()/JSON round-trip before decoding; File objects from a different realm/implementation (two undici versions, mixed polyfills) so the instanceof Blob check fails even for real files.

Common situations: API gateways or middleware that re-serialize request bodies; selectively copying form fields and dropping the file key; manually constructed FormData in tests; Node runtimes with multiple File globals.

Related errors


AI-assisted analysis of facebook/react@eafeac097b (2026-08-21). Data as JSON: /api/errors/99d9c7bf5e2a4bf4. Report an issue: GitHub.