webpack/webpack · error · Error
Data was written with V8 serialization format version ${payl
Error message
Data was written with V8 serialization format version ${payload[1]}, but this Node.js (${process.version}) only reads up to version ${V8_FORMAT_VERSION} What it means
readValuesSection checks the V8 serializer header embedded in a values section and rejects payloads whose format-version byte exceeds what the running Node.js's V8 can decode (lib/serialization/BinaryMiddleware.js:225). V8's wire format only grows, so a higher version byte means the cache was written by a newer Node than the one reading it.
Source
Thrown at lib/serialization/BinaryMiddleware.js:226
return this.read(I32_SIZE).readUInt32LE(0);
}
}
/**
* Reads a section of values written by V8's value serializer.
* @param {ReadState} state read state
* @returns {DeserializedType} values of the section
*/
const readValuesSection = (state) => {
const payloadSize = state.readU32();
const bufferCount = state.readU32();
/** @type {number[]} */
const bufferInfo = [];
for (let i = 0; i < bufferCount * 2; i++) bufferInfo.push(state.readU32());
const payload = state.read(payloadSize);
// a V8 payload opens with 0xff and its format version, which only ever grows
if (payload[0] === 0xff && payload[1] > V8_FORMAT_VERSION) {
throw new Error(
`Data was written with V8 serialization format version ${payload[1]}, but this Node.js (${process.version}) only reads up to version ${V8_FORMAT_VERSION}`
);
}
const values = /** @type {DeserializedType} */ (v8Deserialize(payload));
for (let i = 0; i < bufferCount; i++) {
values[bufferInfo[i * 2]] = state.retainedBuffer(
state.read(bufferInfo[i * 2 + 1])
);
}
return values;
};
/**
* Reads the content items of a lazy section.
* @param {ReadState} state read state
* @returns {SerializedType} content of the lazy value
*/
const readLazySection = (state) => {View on GitHub (pinned to 318421ea8a)
Solutions
- Use the same Node major version that wrote the cache, or upgrade Node.
- Delete the cache directory once and let it rebuild under the current Node.
- Scope `cache.cacheLocation` per Node version (e.g. include `process.versions.node` in the path).
- Set `cache.version` to a string that encodes the Node major so webpack invalidates automatically.
Example fix
// before: shared cache between Node 18 and Node 22
// after: scope cache per node major
const path = require('path');
config.cache = {
type: 'filesystem',
cacheLocation: path.join(__dirname, '.cache', process.versions.node)
}; Defensive patterns
Strategy: fallback
Validate before calling
// Scope or invalidate the cache when the Node major changes
const cacheDir = path.join(__dirname, '.cache', `node-${process.versions.node.split('.')[0]}`);
config.cache = { type: 'filesystem', cacheLocation: cacheDir }; Try / catch
compiler.hooks.failed.tap('V8VersionGuard', (err) => {
if (/V8 serialization format version/.test(err.message)) {
require('fs').rmSync(cacheLocation, { recursive: true, force: true });
console.error('Cache was written by a newer Node; purged. Rebuild.');
}
}); Prevention
- Use the same Node major across writers and readers of a cache.
- Encode the Node major in `cacheLocation` or `cache.version`.
- Do not share caches between Node and Bun.
When it happens
Trigger: A cache written under Node 22 (newer V8 format) is read under Node 18 (older V8). The check `payload[0] === 0xff && payload[1] > V8_FORMAT_VERSION` fires before v8.deserialize is attempted.
Common situations: Downgrading Node locally; CI matrix mixing Node versions while sharing a cache volume; teammates on different Node majors; switching between Node and Bun (which ships its own V8) sharing a cache.
Related errors
- Unexpected lazy element in stream
- Unexpected non-lazy element in stream
- Invalid file version
- Invalid file version ${version}
- No deserializer registered for ${key}
AI-assisted analysis of webpack/webpack@318421ea8a (2026-08-03).
Data as JSON: /data/errors/e7818b22c833669c.json.
Report an issue: GitHub.