node process exits without warning or any error message if you forget finalize(), because archiver fails to keep the event queue going
I spent an hour banging my head against a wall because my program was exiting with code 0 when I tried to pipe a zip to Amazon S3 and await the S3 upload promise. I couldn't get an uncaught exception handler or uncaught rejection handler to fire.
Turns out, I forgot to call archive.finalize(), and in that situation, it reaches a point where the event loop becomes empty (no queued timeouts, intervals, and archive doesn't emit and end or error event) and thus Node exits with code 0.
This is very confusing and one of the most infuriating issues I've ever had to debug.
I realize this is an unavoidable aspect of the current API design, but a different API design would eliminate this danger.
Repro:
const fs = require('fs')
const archiver = require('archiver')
const archive = archiver('zip')
archive.directory('canaries', '')
process.on('uncaughtException', (e) => console.error('uncaughtException', e))
process.on('unhandledRejection', (e) => console.error('unhandledRejection', e))
const out = fs.createWriteStream('test.zip')
archive.pipe(out)
archive.on('error', (e) => console.error('archive error', e))
out.on('error', (e) => console.error('write stream error', e))
archive.on('end', () => console.log('archive end'))
out.on('end', () => console.log('write stream end'))
debugger
Run this script and it will exit 0 with no console output.
Profile the program with --inspect-brk and you'll see this at the end:
The last thing that happens is readdir-glob emits its final event, and then the event loop dies because archiver doesn't put any new events on it.
Imagine if a novice dev forgot to call finalize(). They would never, ever understand why the hell their script was exiting.
Thank you! This saved me a lot of time 😄