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

  1. Use the same Node major version that wrote the cache, or upgrade Node.
  2. Delete the cache directory once and let it rebuild under the current Node.
  3. Scope `cache.cacheLocation` per Node version (e.g. include `process.versions.node` in the path).
  4. 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

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


AI-assisted analysis of webpack/webpack@318421ea8a (2026-08-03). Data as JSON: /data/errors/e7818b22c833669c.json. Report an issue: GitHub.