parcel-bundler/parcel · error · ThrowableDiagnostic

Config result is not hashable because it contains non-serial

Error message

Config result is not hashable because it contains non-serializable objects. Please use config.setCacheKey to set the hash manually.

What it means

To cache a config result, Parcel hashes it. When `config.cacheKey` is null and `config.result` is non-null, it tries `serializeRaw(config.result)`. If the result contains non-serializable values (functions, class instances, symbols, circular structures), serialization throws and Parcel wraps it in this diagnostic telling you to set a manual cache key.

Source

Thrown at packages/core/core/src/requests/ConfigRequest.js:245

  // If there is no result hash set by the transformer, default to hashing the included
  // files if any, otherwise try to hash the config result itself.
  if (config.cacheKey == null) {
    if (config.invalidateOnFileChange.size > 0) {
      hash.writeString(
        await getInvalidationHash(
          [...config.invalidateOnFileChange].map(filePath => ({
            type: 'file',
            filePath,
          })),
          options,
        ),
      );
    } else if (config.result != null) {
      try {
        hash.writeBuffer(serializeRaw(config.result));
      } catch (err) {
        throw new ThrowableDiagnostic({
          diagnostic: {
            message:
              'Config result is not hashable because it contains non-serializable objects. Please use config.setCacheKey to set the hash manually.',
            origin: pluginName,
          },
        });
      }
    }
  } else {
    hash.writeString(config.cacheKey ?? '');
  }

  return hash.finish();
}

export function getConfigRequests(
  configs: Array<Config>,
): Array<ConfigRequest> {

View on GitHub (pinned to 59484858a1)

Solutions

  1. Call `config.setCacheKey(manualHash)` with a stable string derived from the config inputs.
  2. Return only JSON-serializable data (strings, numbers, plain objects/arrays).
  3. If you must return non-serializable objects, store them out-of-band and return a reference/key, then hash the source.

Example fix

// before
config.setResult({ match: new RegExp(pattern) });

// after
config.setResult({ pattern });
config.setCacheKey(createHash(pattern));
Defensive patterns

Strategy: validation

Validate before calling

// If the result isn't serializable, set a manual cache key.
try {
  serializeRaw(config.result);
} catch {
  config.setCacheKey(createHashFromInputs(config));
}

Type guard

function isSerializable(value: mixed): boolean {
  try { JSON.stringify(value); return true; } catch { return false; }
}

Try / catch

try {
  await serializeRaw(config.result);
} catch (err) {
  config.setCacheKey(manualHash);
}

Prevention

When it happens

Trigger: A config plugin returns a result object that contains functions, class instances, or other non-plain-serializable data, and does not call `config.setCacheKey()`.

Common situations: Config loaders that return compiled regexes, function factories, or third-party class instances; configs that capture closures.

Related errors


AI-assisted analysis of parcel-bundler/parcel@59484858a1 (2026-08-13). Data as JSON: /api/errors/7d988a592e0f478a. Report an issue: GitHub.