facebook/react · error · Error

taintUniqueValue cannot taint objects or functions. Try tain

Error message

taintUniqueValue cannot taint objects or functions. Try taintObjectReference instead.

What it means

taintUniqueValue registers a specific high-entropy value (string, bigint, or binary view) in a global registry keyed by the value itself. Objects and functions are reference-unique but not value-unique, so they cannot be looked up this way; React throws and points you to taintObjectReference, which uses a WeakMap keyed by identity.

Source

Thrown at packages/react/src/ReactTaint.js:93

  let entryValue: string | bigint;
  if (typeof value === 'string' || typeof value === 'bigint') {
    // Use as is.
    entryValue = value;
  } else if (
    value instanceof TypedArrayConstructor ||
    value instanceof DataView
  ) {
    // For now, we just convert binary data to a string so that we can just use the native
    // hashing in the Map implementation. It doesn't really matter what form the string
    // take as long as it's the same when we look it up.
    // We're not too worried about collisions since this should be a high entropy value.
    TaintRegistryByteLengths.add(value.byteLength);
    entryValue = binaryToComparableString(value);
  } else {
    // $FlowFixMe[invalid-compare]
    const kind = value === null ? 'null' : typeof value;
    if (kind === 'object' || kind === 'function') {
      throw new Error(
        'taintUniqueValue cannot taint objects or functions. Try taintObjectReference instead.',
      );
    }
    throw new Error(
      'Cannot taint a ' +
        kind +
        ' because the value is too general and not unique enough to block globally.',
    );
  }
  const existingEntry = TaintRegistryValues.get(entryValue);
  if (existingEntry === undefined) {
    TaintRegistryValues.set(entryValue, {
      message,
      count: 1,
    });
  } else {
    existingEntry.count++;
  }

View on GitHub (pinned to eafeac097b)

Solutions

  1. Use taintObjectReference(message, obj) for objects and functions
  2. If the sensitive part is a property of the object, extract it and taint that unique string/binary value with taintUniqueValue
  3. Review the taint API split: unique values -> taintUniqueValue, references -> taintObjectReference

Example fix

// before
taintUniqueValue(msg, lifetime, userObject); // object value -> throws

// after
taintObjectReference(msg, userObject);
// and/or for the sensitive field:
taintUniqueValue(msg, lifetime, userObject.apiKey);
Defensive patterns

Strategy: type-guard

Validate before calling

// Route to the correct taint API by value type
function taintAny(message: string, lifetime: object, value: unknown) {
  if (value != null && (typeof value === 'object' || typeof value === 'function')) {
    taintObjectReference(message, value);
  } else {
    taintUniqueValue(message, lifetime, value as string | bigint | $ArrayBufferView);
  }
}

Type guard

const isTaintableObject = (v: unknown): v is object | Function =>
  v != null && (typeof v === 'object' || typeof v === 'function');

Prevention

When it happens

Trigger: Calling taintUniqueValue(message, lifetime, someObject) or taintUniqueValue(message, lifetime, someFunction) as the value argument.

Common situations: Trying to block accidental serialization of a user object or class instance; assuming one taint API covers all types when hardening a Server Components app.

Related errors


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