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
- Call `config.setCacheKey(manualHash)` with a stable string derived from the config inputs.
- Return only JSON-serializable data (strings, numbers, plain objects/arrays).
- 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
- Return only JSON-serializable config results when possible.
- Call config.setCacheKey() whenever you return functions, regexes, or class instances.
- Derive the manual key from stable inputs (file contents, versions), not runtime state.
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
- Local plugins are not supported in Parcel config packages. P
- Could not determine version of ${pluginName} in ${path.relat
- IDBCache is only supported in the browser
- Bundle is not inline and unable to retrieve contents
- Only one spread parameter can be included in a config pipeli
AI-assisted analysis of parcel-bundler/parcel@59484858a1 (2026-08-13).
Data as JSON: /api/errors/7d988a592e0f478a.
Report an issue: GitHub.