This error occurs when Node.js's zlib module fails to decompress data due to corrupted input, incorrect compression format, or header mismatches. The decompression algorithm encounters data that doesn't conform to the expected zlib/gzip format.
The "zlib inflate error" indicates that Node.js's zlib decompression module encountered data it cannot properly decompress. This error typically manifests with error codes like Z_DATA_ERROR (corrupted or invalid data) or Z_BUF_ERROR (incomplete data). The zlib module in Node.js handles compression and decompression using various algorithms (gzip, deflate, etc.). When inflate() or gunzip() fails, it means the compressed data stream doesn't conform to the expected format, the data is corrupted, or there's a mismatch between the compression method used and the decompression method being applied. This error can occur during HTTP response decompression, file decompression, or when working with compressed buffers in your application.
First, confirm that your compressed data is valid and complete. Try decompressing it with standard command-line tools:
# For gzip files
gunzip -t file.gz
# Or using zcat to test
zcat file.gz > /dev/nullIf the data is being received over HTTP, check the Content-Encoding headers and ensure the full response is received before decompression.
Ensure you're using the correct decompression function for your data format:
const zlib = require('zlib');
// For gzip data (includes headers)
zlib.gunzip(buffer, (err, result) => {
if (err) {
console.error('Gunzip failed:', err.code);
return;
}
console.log(result.toString());
});
// For raw deflate data (no headers)
zlib.inflate(buffer, (err, result) => {
if (err) {
console.error('Inflate failed:', err.code);
return;
}
console.log(result.toString());
});
// For auto-detection (works with both)
zlib.unzip(buffer, (err, result) => {
if (err) {
console.error('Unzip failed:', err.code);
return;
}
console.log(result.toString());
});Use unzip() when the compression format is unknown.
The streaming API (createGunzip, createInflate) often handles edge cases better than callback-based methods:
const zlib = require('zlib');
const fs = require('fs');
// Instead of gunzip()
const gunzip = zlib.createGunzip();
const input = fs.createReadStream('file.gz');
const output = fs.createWriteStream('file.txt');
gunzip.on('error', (err) => {
console.error('Decompression error:', err.code, err.message);
});
input.pipe(gunzip).pipe(output);This approach provides better error handling and works with partial data streams.
Implement proper error handling for different zlib error codes:
const zlib = require('zlib');
function safeDecompress(buffer: Buffer): Promise<Buffer> {
return new Promise((resolve, reject) => {
zlib.gunzip(buffer, (err, result) => {
if (err) {
switch (err.code) {
case 'Z_DATA_ERROR':
reject(new Error('Corrupted or invalid compressed data'));
break;
case 'Z_BUF_ERROR':
reject(new Error('Incomplete compressed data'));
break;
case 'Z_MEM_ERROR':
reject(new Error('Insufficient memory for decompression'));
break;
default:
reject(new Error(`Decompression failed: ${err.message}`));
}
return;
}
resolve(result);
});
});
}
// Usage
try {
const decompressed = await safeDecompress(compressedBuffer);
console.log(decompressed.toString());
} catch (error) {
console.error('Decompression failed:', error.message);
}When decompressing HTTP responses, ensure proper handling of Content-Encoding headers:
const https = require('https');
const zlib = require('zlib');
https.get('https://example.com/api', (res) => {
const chunks: Buffer[] = [];
res.on('data', (chunk) => {
chunks.push(chunk);
});
res.on('end', () => {
const buffer = Buffer.concat(chunks);
// Check Content-Encoding header
const encoding = res.headers['content-encoding'];
if (encoding === 'gzip') {
zlib.gunzip(buffer, (err, decompressed) => {
if (err) {
console.error('Failed to decompress gzip:', err.message);
return;
}
console.log(decompressed.toString());
});
} else if (encoding === 'deflate') {
zlib.inflate(buffer, (err, decompressed) => {
if (err) {
console.error('Failed to decompress deflate:', err.message);
return;
}
console.log(decompressed.toString());
});
} else {
console.log(buffer.toString());
}
});
}).on('error', (err) => {
console.error('Request failed:', err.message);
});Alternatively, let Node.js handle decompression automatically by not setting custom encoding.
WindowBits Configuration: The windowBits parameter controls the compression window size and format. For raw deflate streams, you may need to specify windowBits manually. Note that Node.js automatically upgrades windowBits from 8 to 9 for compatibility with zlib library changes between versions 1.2.8 and 1.2.11.
Memory Considerations: Large decompression operations can consume significant memory. Use the maxOutputLength option to limit output size and prevent memory exhaustion:
zlib.gunzip(buffer, { maxOutputLength: 50 * 1024 * 1024 }, callback);Multiple Compression Layers: Some servers send responses with multiple compression layers (e.g., "Content-Encoding: gzip, deflate"). In these cases, you need to decompress in reverse order. Modern HTTP clients like undici handle this automatically.
Empty Buffer Edge Case: Some Node.js versions throw exceptions when decompressing previously compressed empty buffers. Validate buffer contents before decompression or handle this as a special case.
Streaming vs. Callback API: The streaming API (createGunzip, createInflate) is generally more robust for handling partial data and provides better backpressure management for large files. The callback API loads the entire buffer into memory.
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