The Z_DATA_ERROR occurs when Node.js zlib detects corrupted or invalid compressed data during decompression. This typically happens when attempting to decompress data with incorrect headers, truncated content, or using the wrong decompression method.
The Z_DATA_ERROR error is thrown by Node.js's zlib module when it encounters compressed data that cannot be properly decompressed. This error code (-3) specifically indicates that the compressed data stream is corrupted, has an invalid header (such as missing or incorrect gzip magic bytes 1f 8b), or is in an incompatible compression format. The zlib library performs header validation before attempting decompression. When the header check fails, it immediately returns Z_DATA_ERROR to prevent processing corrupt data. This error can occur with any of the zlib decompression methods including gunzip(), inflateSync(), unzip(), and their streaming equivalents. Common scenarios include attempting to decompress data that was truncated during transmission, using the wrong decompression algorithm for the actual compression format (e.g., trying to inflate a ZIP archive instead of using a ZIP-specific library), or processing data that was never actually compressed in the first place.
Check the first few bytes of your data to confirm it has a valid compression header:
const buffer = yourCompressedData;
// Check for gzip magic bytes (1f 8b)
if (buffer[0] === 0x1f && buffer[1] === 0x8b) {
console.log('Valid gzip header detected');
} else {
console.log('Not a gzip file. First bytes:', buffer.slice(0, 4).toString('hex'));
}If the data doesn't have the expected header, it's likely not compressed or uses a different format.
Match your decompression method to the actual compression format:
const zlib = require('zlib');
// For gzip compressed data
zlib.gunzip(buffer, (err, decompressed) => {
if (err) {
if (err.code === 'Z_DATA_ERROR') {
console.error('Invalid gzip data');
}
return;
}
console.log(decompressed.toString());
});
// For deflate compressed data (no gzip wrapper)
zlib.inflate(buffer, (err, decompressed) => {
// ...
});
// For unknown format (auto-detect)
zlib.unzip(buffer, (err, decompressed) => {
// ...
});For ZIP archives, use a dedicated library like adm-zip or jszip instead of zlib.
Some data works with streaming APIs when callback methods fail:
const zlib = require('zlib');
const { pipeline } = require('stream');
const fs = require('fs');
// Create a gunzip stream
const gunzip = zlib.createGunzip();
const chunks = [];
gunzip.on('data', (chunk) => {
chunks.push(chunk);
});
gunzip.on('end', () => {
const decompressed = Buffer.concat(chunks);
console.log('Decompressed successfully');
});
gunzip.on('error', (err) => {
if (err.code === 'Z_DATA_ERROR') {
console.error('Corrupted compressed data');
}
});
// Write data to stream
gunzip.write(buffer);
gunzip.end();Streaming APIs can be more forgiving with certain edge cases.
If you expect incomplete data, configure custom flush behavior:
const zlib = require('zlib');
const options = {
finishFlush: zlib.constants.Z_SYNC_FLUSH,
// Allow partial data decompression
};
zlib.gunzip(buffer, options, (err, result) => {
if (err && err.code === 'Z_DATA_ERROR') {
console.error('Could not decompress, data may be truncated');
} else {
console.log('Decompressed (possibly partial):', result);
}
});This won't fix corrupted data but can help with incomplete streams.
When decompressing HTTP responses, ensure correct Content-Encoding handling:
const https = require('https');
const zlib = require('zlib');
https.get('https://example.com/data', (res) => {
const encoding = res.headers['content-encoding'];
let stream = res;
console.log('Content-Encoding:', encoding);
// Only decompress if actually compressed
if (encoding === 'gzip') {
stream = res.pipe(zlib.createGunzip());
} else if (encoding === 'deflate') {
stream = res.pipe(zlib.createInflate());
}
const chunks = [];
stream.on('data', (chunk) => chunks.push(chunk));
stream.on('end', () => {
const data = Buffer.concat(chunks);
console.log('Response:', data.toString());
});
stream.on('error', (err) => {
console.error('Decompression error:', err.code);
});
});Many HTTP clients auto-decompress, so manual decompression causes Z_DATA_ERROR.
Implement robust error handling to catch and report Z_DATA_ERROR:
const zlib = require('zlib');
function safeDecompress(buffer) {
return new Promise((resolve, reject) => {
zlib.gunzip(buffer, (err, result) => {
if (err) {
if (err.code === 'Z_DATA_ERROR') {
reject(new Error('Invalid or corrupt compressed data'));
} else if (err.code === 'Z_BUF_ERROR') {
reject(new Error('Incomplete compressed data'));
} else {
reject(err);
}
return;
}
resolve(result);
});
});
}
// Usage
safeDecompress(compressedBuffer)
.then(data => console.log('Success:', data.toString()))
.catch(err => console.error('Decompression failed:', err.message));Binary Data Encoding: When handling compressed data from external sources, always treat it as binary. Converting to string and back using the wrong encoding (e.g., UTF-8 instead of base64 or hex) will corrupt the data and cause Z_DATA_ERROR.
Platform-Specific Issues: Some Node.js builds have exhibited zlib bugs related to compiler optimization issues (particularly with clang-12 in release mode). If you encounter Z_DATA_ERROR only in production or on specific platforms, verify your Node.js build and consider testing with different Node.js versions.
ZIP vs GZIP: ZIP archives (.zip files) use a different format than gzip (.gz files) despite both using deflate compression internally. ZIP files have directory structures and multiple file entries, while gzip compresses a single stream. Use libraries like adm-zip, jszip, or unzipper for ZIP files, not the zlib module.
Multiple Content-Encoding: HTTP responses with Content-Encoding: gzip, deflate should be decompressed in reverse order (deflate first, then gzip). However, most HTTP clients handle this automatically. Manual double-decompression often causes Z_DATA_ERROR because the client already decompressed once.
inflateSync vs inflate: When using synchronous methods like inflateSync(), be aware that they only support data compressed with full flush points (Z_FULL_FLUSH), not partial sync points (Z_SYNC_FLUSH). This restriction can cause Z_DATA_ERROR with certain compressed streams that work fine with async methods.
Memory Corruption: In rare cases, Z_DATA_ERROR can indicate memory corruption in your Node.js process rather than corrupt source data. If the error is intermittent or non-reproducible, check for buffer overruns, native addon issues, or resource exhaustion elsewhere in your application.
Error: Listener already called (once event already fired)
EventEmitter listener already called with once()
Error: EACCES: permission denied, open '/root/file.txt'
EACCES: permission denied
Error: Invalid encoding specified (stream encoding not supported)
How to fix Invalid encoding error in Node.js readable streams
Error: EINVAL: invalid argument, open
EINVAL: invalid argument, open
TypeError: readableLength must be a positive integer (stream config)
TypeError: readableLength must be a positive integer in Node.js streams