Skip to content

fix: prevent portal generate hang on Node 22+ (replace extract-zip with adm-zip)#283

Merged
saeedjamshaid merged 1 commit into
devfrom
saeedjamshaid/fix-node24-portal-generate-hang
Jun 10, 2026
Merged

fix: prevent portal generate hang on Node 22+ (replace extract-zip with adm-zip)#283
saeedjamshaid merged 1 commit into
devfrom
saeedjamshaid/fix-node24-portal-generate-hang

Conversation

@saeedjamshaid

@saeedjamshaid saeedjamshaid commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Problem

On Node 22+ (reproduced in GitHub Actions on Node 24), apimatic portal generate prints Portal generated successfully. and then crashes:

Warning: Detected unsettled top-level await at .../bin/run.js
Error: Process completed with exit code 13

Verified via runner logs (NODE_DEBUG + step markers + a beforeExit active-resources dump): the download succeeds and every portal file is written to disk — the hang is in ZipService.unArchive.

Root cause

extract-zip@2.0.1 extracts each entry via await pipeline(readStream, writeStream) and only reads the next entry once that resolves; the whole op resolves on yauzl's 'close'. yauzl 2.10 builds STORED entries' read streams on the unmaintained fd-slicer@1.1.0, and on Node 22+ those streams deliver every byte but never emit end. So the last entry's pipeline never resolves → readEntry() is never called again → 'close' never fires → unArchive's promise stays pending forever, even though the files are already written. The event loop drains with the top-level await execute() still pending → exit 13. (The nested STORED SDK .zip inside the portal is the entry that trips it.)

active resources at beforeExit: [ 'PipeWrap', 'PipeWrap' ] (only stdout/stderr) confirmed a dangling promise rather than an I/O stall.

Fix

Replace extract-zip with adm-zip in ZipService.unArchive. adm-zip extracts synchronously (extractAllTo) with no per-entry read streams — no fd-slicer, no end-event handshake — eliminating this class of hang. The MAX_FILES / MAX_SIZE guards are preserved, and adm-zip sanitizes entry paths internally (zip-slip protection). Removes the now-unused extract-zip dependency (and its transitive yauzl/fd-slicer).

Testing

Confirmed green on Node 24 via a dedicated GitHub Actions harness installing the built tarball: the portal now generates, saves, and the process exits 0.

extract-zip's yauzl/fd-slicer read streams for STORED zip entries never emit
`end` on Node 22+, so unArchive never resolves even after every file has been
written; the event loop then drains with a pending top-level await and the CLI
exits with code 13 (reproduced in CI on Node 24). Replace extract-zip with
adm-zip's synchronous extraction (no per-entry streams), keeping the existing
file-count/size guards. Removes the now-unused extract-zip dependency.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@saeedjamshaid saeedjamshaid merged commit ad87f47 into dev Jun 10, 2026
4 checks passed
@saeedjamshaid saeedjamshaid deleted the saeedjamshaid/fix-node24-portal-generate-hang branch June 10, 2026 09:04
github-actions Bot pushed a commit that referenced this pull request Jun 11, 2026
# [1.1.0-beta.18](v1.1.0-beta.17...v1.1.0-beta.18) (2026-06-11)

### Bug Fixes

* prevent portal generate hang on Node 22+ by extracting with adm-zip ([#283](#283)) ([#284](#284)) ([e3bac3e](e3bac3e))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants