Profiles·Public

unzipper

semver>=0.9.0 <0.13.0postconditions17functions9last verified2026-04-17coverage score75%

Postconditions — what we check

  • Parse · corrupt-zip-error
    error
    WhenInput stream contains a corrupt or invalid zip file
    ThrowsError emitted on the Parse stream (e.g., 'end of file' or Zlib Z_BUF_ERROR)
    Required handlingCaller MUST attach an error handler to the Parse stream. Use parseStream.on('error', handler) or handle in the pipe chain. Without an error handler, corrupt zip errors will crash the process as unhandled stream errors.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1][2]
  • Parse · entry-not-consumed
    error
    WhenAn entry stream emitted by Parse is not read or drained
    ThrowsThe entire parse stream backs up and hangs indefinitely
    Required handlingCaller MUST either consume each entry's stream data or call entry.autodrain() on entries that are not needed. Failure to drain entries causes the stream to stall.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1][3]
  • Extract · extraction-io-error
    error
    WhenFile system error during extraction (permission denied, disk full, invalid path)
    ThrowsError emitted on the Extract stream
    Required handlingCaller MUST attach an error handler or use promise-based .promise() method. Example: fs.createReadStream(zipFile).pipe(unzipper.Extract({path})).promise() The promise form rejects with the IO error allowing try-catch handling.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1]
  • Extract · corrupt-zip-extract-error
    error
    WhenInput contains a corrupt zip file during Extract
    ThrowsError emitted on the Extract stream
    Required handlingCaller MUST handle stream errors when using Extract. Use .promise() for await-able error handling or attach an error listener to the stream. Files partially extracted before the error are NOT automatically cleaned up.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1][4]
  • Open · file-not-found
    error
    WhenThe file path passed to Open.file() does not exist or cannot be read
    ThrowsError with ENOENT or EACCES code
    Required handlingCaller MUST wrap Open.file() in try-catch or handle promise rejection. Open.file() returns a promise that rejects with filesystem errors.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1]
  • Open · invalid-zip-open-error
    error
    WhenFile exists but is not a valid zip file (wrong magic bytes or corrupt central directory)
    ThrowsError indicating invalid zip format
    Required handlingCaller MUST wrap Open.file() in try-catch. Invalid zip files cause rejection when the central directory cannot be parsed. Validate the file is a zip before processing.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1]
  • Open · entry-extraction-error
    error
    WhenA specific entry within the zip cannot be extracted (corrupt entry, unsupported compression)
    ThrowsError emitted on the entry extraction stream
    Required handlingCaller MUST handle errors on individual entry streams. attach .on('error', handler) to each entry's stream, or use entry.buffer() in a try-catch block. Entry errors do not propagate to the parent directory stream automatically.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1]
  • ParseOne · parseone-pattern-not-found
    error
    Whenfs.createReadStream(zipFile).pipe(unzipper.ParseOne(/pattern/)) is piped and the source archive contains no entries matching the provided regex or string pattern. The Duplex stream fully processes all entries and emits 'PATTERN_NOT_FOUND' error on the output stream after the archive completes. Also triggered when the archive is empty. This is the most common silent failure in code using ParseOne — callers that don't attach an error handler receive an unhandled stream error that crashes the process.
    ThrowsError with message 'PATTERN_NOT_FOUND' — emitted as a stream error event on the output (Duplex) stream returned by ParseOne(). This is NOT a thrown synchronous exception — it propagates via stream.emit('error', ...) or via the promise rejection when using .buffer(). Confirmed from parseOne.js: `outStream.emit('error', new Error('PATTERN_NOT_FOUND'))` when the 'finish' event fires without setting `found = true`.
    Required handlingUse the .buffer() promise form with try-catch for reliable error handling: try { const content = await fs.createReadStream(zipFile) .pipe(unzipper.ParseOne(/config\.json$/)) .buffer(); return JSON.parse(content.toString()); } catch (error) { if (error.message === 'PATTERN_NOT_FOUND') { console.warn('Expected file not found in archive'); return null; // Or throw a more descriptive error } throw error; } When using the stream form (without .buffer()), attach an error handler: const extracted = stream.pipe(unzipper.ParseOne('target.txt')); extracted.on('error', (err) => { if (err.message === 'PATTERN_NOT_FOUND') { ... } }); Note: ParseOne() without a pattern extracts the FIRST entry — no PATTERN_NOT_FOUND is possible unless the archive itself is empty or corrupt.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[5][6]
  • ParseOne · parseone-corrupt-archive-error
    error
    WhenThe source ZIP stream contains a corrupt or invalid archive (invalid signature, truncated data, malformed local file headers). The Parse stream underlying ParseOne emits an error that propagates to the ParseOne output stream. This is the same corruption error as the Parse contract, but specific to the single-entry extraction workflow.
    ThrowsError with message 'invalid signature: 0x<hex>' — from parse.js when local file header signature bytes do not match 0x04034b50. Error with message 'FILE_ENDED' — from PullStream.js when the input stream ends before expected bytes are read (truncated archive). Both propagate via stream.emit('error', ...) or reject .buffer() promise.
    Required handlingAlways handle errors when piping into ParseOne: try { const buffer = await readStream .pipe(unzipper.ParseOne('README.md')) .buffer(); return buffer.toString(); } catch (error) { if (error.message && error.message.startsWith('invalid signature')) { throw new Error('Not a valid ZIP file'); } if (error.message === 'FILE_ENDED') { throw new Error('ZIP file is truncated or incomplete'); } throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[6][7]
  • Open.buffer · open-buffer-invalid-zip
    error
    WhenThe Buffer passed to Open.buffer() does not contain a valid ZIP archive (wrong magic bytes, no central directory, corrupt structure). The directory parser reads from the buffer's tail looking for the end-of-central-directory record, and if the buffer is not a ZIP (e.g., a PDF, an image, or empty bytes), the directory parser will emit FILE_ENDED or invalid signature errors.
    ThrowsError with message 'FILE_ENDED' — when PullStream exhausts the buffer before finding the end-of-central-directory record. Common when the buffer is not a ZIP file at all, or is empty/truncated. Error with message 'invalid zip64 end of central dir locator signature ...' — when the buffer contains what looks like a ZIP64 header but has corrupt signature bytes. These propagate as Promise rejections from Open.buffer().
    Required handlingWrap Open.buffer() in try-catch: try { const directory = await unzipper.Open.buffer(fileBuffer); const files = await directory.files; for (const file of files) { if (file.type === 'File') { const content = await file.buffer(); // process content } } } catch (error) { if (error.message === 'FILE_ENDED') { throw new Error('Buffer is not a valid ZIP archive (possibly empty or wrong format)'); } throw error; } For user-uploaded files, validate the content-type header and the magic bytes (ZIP files start with 0x504B0304 — 'PK\x03\x04') before calling Open.buffer().
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[5][8]
  • Open.url · open-url-missing-content-length
    warning
    WhenThe remote server does not return a Content-Length header in its response. Open.url() makes a HEAD-like request to determine the file size before making range requests. If the server omits Content-Length (many CDNs with chunked transfer encoding, servers with gzip compression enabled, or servers that don't support it), the size() call rejects immediately with 'Missing content length header'. This is a common failure when using Open.url() against APIs or cloud storage endpoints that do not expose file size in headers.
    ThrowsError with message 'Missing content length header' — confirmed from Open/index.js: `reject(new Error('Missing content length header'))` when the response to the initial size-detection request has no Content-Length. This is a Promise rejection (not a stream error) since the failure occurs during the initial setup of the CentralDirectory, before any streaming begins.
    Required handlingWrap Open.url() in try-catch and handle the 'Missing content length header' error specifically: const request = require('request'); // Or an alternative HTTP library try { const directory = await unzipper.Open.url(request, { url: 'https://example.com/archive.zip', headers: { 'User-Agent': 'MyApp/1.0' } }); const files = await directory.files; // process files } catch (error) { if (error.message === 'Missing content length header') { // Fall back to downloading the full file console.warn('Remote server does not support range requests, falling back to full download'); const response = await fetch(zipUrl); const buffer = Buffer.from(await response.arrayBuffer()); const directory = await unzipper.Open.buffer(buffer); // ... } throw error; } Note: Open.url() is typically used with the deprecated `request` library. For modern code, prefer downloading the full ZIP with fetch() and using Open.buffer() instead.
    costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[5][9]
  • Open.url · open-url-network-error
    error
    WhenOpen.url() fails because the URL is unreachable (DNS failure, connection refused, SSL error, HTTP error response). The underlying request library emits an 'error' event that is forwarded to the Promise rejection.
    ThrowsError from the request library — the specific type depends on which library is passed as the first argument. With the `request` library, network errors are Error objects with message like 'ENOTFOUND', 'ECONNREFUSED', or 'ETIMEDOUT'. HTTP 4xx/5xx responses do NOT automatically reject — the request library's behavior determines this.
    Required handlingWrap Open.url() in try-catch and handle network errors: try { const directory = await unzipper.Open.url(request, zipUrl); } catch (error) { console.error('Failed to open remote ZIP:', error.message); throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[9]
  • Open.s3_v3 · open-s3v3-not-found-or-access-denied
    error
    WhenOpen.s3_v3() is called and either: (a) The S3 object does not exist (NoSuchKey from HeadObjectCommand) (b) The bucket does not exist (NoSuchBucket) (c) The caller does not have GetObject/HeadObject permissions (AccessDenied / 403) The HeadObjectCommand is sent during the initial size() call inside directory(), and its rejection propagates as a Promise rejection from Open.s3_v3().
    ThrowsAWS SDK v3 S3ServiceException subclasses: - NoSuchKey (404) — S3 object doesn't exist at the specified key - NoSuchBucket (404) — S3 bucket doesn't exist - S3ServiceException with $metadata.httpStatusCode === 403 — access denied These are thrown by client.send() and propagate through the async HeadObjectCommand. Check: error.$metadata?.httpStatusCode or error.name for specific error types.
    Required handlingWrap Open.s3_v3() in try-catch and handle common S3 errors: const { S3Client, NoSuchKey } = require('@aws-sdk/client-s3'); const s3 = new S3Client({ region: 'us-east-1' }); try { const directory = await unzipper.Open.s3_v3(s3, { Bucket: 'my-bucket', Key: 'archives/data.zip', }); const files = await directory.files; for (const file of files) { if (file.type === 'File') { const content = await file.buffer(); // process content } } } catch (error) { if (error.name === 'NoSuchKey') { throw new Error(`Archive not found: ${params.Key}`); } if (error.$metadata?.httpStatusCode === 403) { throw new Error('Access denied to S3 archive — check IAM permissions'); } throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[5][9][10]
  • CentralDirectory.extract · extract-path-missing
    error
    WhenCentralDirectory.extract() is called without an opts.path parameter, or with opts.path set to undefined/null/empty string. The path is required for extracting files to disk. The function throws synchronously (not as a Promise rejection) when this check fails, which means the error may propagate differently depending on whether the caller is in an async context.
    ThrowsError with message 'PATH_MISSING' — thrown synchronously in the extract function: `if (!opts || !opts.path) throw new Error('PATH_MISSING')`. Confirmed from directory.js. In an async function awaiting extract(), this synchronous throw IS caught as a Promise rejection by the async function wrapper. In .then() chains, it also propagates as a rejection. Always use try-catch.
    Required handlingAlways provide opts.path and wrap in try-catch: const directory = await unzipper.Open.file('archive.zip'); try { await directory.extract({ path: '/tmp/extracted', concurrency: 4 }); } catch (error) { if (error.message === 'PATH_MISSING') { throw new Error('Extraction path is required'); } throw error; } Use path.resolve() to get an absolute path — the function normalizes the path internally with path.resolve(path.normalize(opts.path)).
    costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[5][8]
  • CentralDirectory.extract · extract-filesystem-error
    error
    WhenCentralDirectory.extract() fails because of filesystem errors during extraction: - Destination path does not exist and cannot be created (EACCES, EROFS) - Disk is full (ENOSPC) - Destination path is read-only (EACCES) - An individual entry file stream encounters a compression error The extract() method uses fs-extra's ensureDir() and fs.createWriteStream() for each entry. Failures in any entry propagate as Promise rejections via Bluebird.map's error handling.
    ThrowsError with EACCES — permission denied writing to destination directory. Error with ENOSPC — no space left on device. Error with ENOENT — parent directory of a nested path cannot be created (rare, since ensureDir is used, but can happen with race conditions). Entry stream errors (zlib errors like 'Z_BUF_ERROR') for corrupt compressed entries.
    Required handlingWrap extract() in try-catch and handle common filesystem errors: const { mkdir } = require('fs/promises'); const destPath = path.resolve('/tmp', 'extracted-' + Date.now()); await mkdir(destPath, { recursive: true }); const directory = await unzipper.Open.file('archive.zip'); try { await directory.extract({ path: destPath }); } catch (error) { if (error.code === 'EACCES') { throw new Error(`Cannot write to ${destPath}: permission denied`); } if (error.code === 'ENOSPC') { throw new Error('Disk full — extraction aborted'); } throw error; }
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[8]
  • Entry.buffer · entry-buffer-missing-password
    error
    Whenfile.buffer() (or entry.buffer()) is called on an encrypted ZIP entry without providing the password, or with a wrong password. Encrypted ZIP entries have the encryption flag set (vars.flags & 0x01). The password check occurs during stream setup — before any decompressed data is read — so failure is immediate. This is common when processing user-uploaded ZIP files that may be encrypted, or when building ZIP processors that need to handle both encrypted and unencrypted archives.
    ThrowsError with message 'MISSING_PASSWORD' — thrown when the entry has encryption flag set but no password was provided. Confirmed from Open/unzip.js: `if (!_password) throw new Error('MISSING_PASSWORD')`. Error with message 'BAD_PASSWORD' — thrown when the provided password fails the verification byte check. Confirmed from Open/unzip.js: `if (header[11] !== check) throw new Error('BAD_PASSWORD')`. Both errors are thrown synchronously in the .vars Promise chain and propagate as rejections when awaiting file.buffer() or entry.buffer().
    Required handlingCheck for encrypted entries and handle appropriately: // When using Open.*: const directory = await unzipper.Open.file('archive.zip'); const files = await directory.files; for (const file of files) { if (file.type !== 'File') continue; try { const content = await file.buffer(password); // pass password or undefined processContent(content); } catch (error) { if (error.message === 'MISSING_PASSWORD') { console.error(`${file.path} is encrypted — password required`); continue; // Skip or prompt user } if (error.message === 'BAD_PASSWORD') { console.error(`Wrong password for ${file.path}`); continue; } throw error; } } // When using Parse() streams: stream.pipe(unzipper.Parse()).on('entry', async (entry) => { try { const content = await entry.buffer(); } catch (error) { if (error.message === 'MISSING_PASSWORD') { entry.autodrain(); // Drain the entry to keep the stream moving } } }); Note: The encryption flag can be checked via entry.vars (a Promise) — but this is internal API. Prefer try-catch with specific error messages.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[5][11]
  • Entry.buffer · entry-buffer-decompression-error
    error
    Whenentry.buffer() or file.buffer() is called and the compressed entry data is corrupt or uses an unsupported compression method. The zlib.createInflateRaw() stream decompresses the data; if the compressed bytes are corrupt, zlib emits an error that propagates through the entry stream into BufferStream's rejection. Common with partially-downloaded ZIP files, network-interrupted transfers, or archives where individual entries are corrupt even though the central directory is intact.
    ThrowsError from zlib — typically 'invalid block type', 'unknown compression method', or 'Z_BUF_ERROR'. Propagates via entry.on('error', reject) in BufferStream. Error with message 'FILE_ENDED' — if the source stream ends before the expected compressed bytes are read (truncated entry).
    Required handlingWrap entry.buffer() / file.buffer() in try-catch for each entry independently: const directory = await unzipper.Open.buffer(zipBuffer); const files = await directory.files; const results = await Promise.allSettled( files .filter(f => f.type === 'File') .map(async (file) => { try { return { path: file.path, content: await file.buffer() }; } catch (error) { console.warn(`Failed to read ${file.path}: ${error.message}`); return { path: file.path, content: null, error: error.message }; } }) ); Use Promise.allSettled() rather than Promise.all() when processing multiple entries so one corrupt entry doesn't abort the entire batch.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[12][11]

Sources

Every postcondition cites at least one of these. Numbered to match the footnotes above.

  1. [1]github.com/ZJONSSON/node-unzipperhttps://github.com/ZJONSSON/node-unzipper#readme
  2. [2]github.com/ZJONSSON/node-unzipperhttps://github.com/ZJONSSON/node-unzipper/issues/213
  3. [3]github.com/ZJONSSON/node-unzipperhttps://github.com/ZJONSSON/node-unzipper/issues/98
  4. [4]github.com/ZJONSSON/node-unzipperhttps://github.com/ZJONSSON/node-unzipper/issues/286
  5. [5]raw.githubusercontent.com/ZJONSSON/node-unzipperhttps://raw.githubusercontent.com/ZJONSSON/node-unzipper/master/README.md
  6. [6]github.com/ZJONSSON/node-unzipperhttps://github.com/ZJONSSON/node-unzipper/blob/master/lib/parseOne.js
  7. [7]github.com/ZJONSSON/node-unzipperhttps://github.com/ZJONSSON/node-unzipper/blob/master/lib/parse.js
  8. [8]github.com/ZJONSSON/node-unzipperhttps://github.com/ZJONSSON/node-unzipper/blob/master/lib/Open/directory.js
  9. [9]github.com/ZJONSSON/node-unzipperhttps://github.com/ZJONSSON/node-unzipper/blob/master/lib/Open/index.js
  10. [10]docs.aws.amazon.com/AWSJavaScriptSDK/v3https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/command/HeadObjectCommand/
  11. [11]github.com/ZJONSSON/node-unzipperhttps://github.com/ZJONSSON/node-unzipper/blob/master/lib/Open/unzip.js
  12. [12]github.com/ZJONSSON/node-unzipperhttps://github.com/ZJONSSON/node-unzipper/blob/master/lib/BufferStream.js
Need a different package?
Request a profile