What happened
importDisk pipes the archive read stream without an error listener on the source, and pipe() does not forward errors — so a read failure becomes an unhandled 'error' event and kills the daemon.
// packages/server/src/executor/docker.ts:376
createReadStream(srcPath).pipe(meter);
The twin path for the in-container case, at :1261-1265, names and handles exactly this hazard, so the omission here is inconsistent with the file's own practice.
Trigger: stat(srcPath) at :365 succeeds but the read then fails — host disk EIO, or the archive file removed between the stat and the stream open.
Expected: the failure reaches the caller honestly, and the catch at :385-388 tears down the half-configured disk ("Leave no half-disk behind the verb's own failure").
Got: the read stream's 'error' has no listener, so it becomes an uncaughtException — there is no process.on('uncaughtException') anywhere in the server — and the daemon exits. The cleanup catch never runs.
Rare (needs a host-side fault) and startup reconcile limits the damage afterwards, but the fix is one line.
dor doctor output
Not applicable — defect found by reading the executor; the trigger is a host I/O fault rather than a configuration problem.
Environment
Installed via: from source (this is a source audit, not a field report)
Dormice version/commit: main @ 336b722
OS: n/a
Executor: docker
Daemon logs (if relevant)
None captured.
Suggested fix
Mirror the shape already used at :1265:
const src = createReadStream(srcPath);
src.on('error', (err) => meter.destroy(err));
src.pipe(meter);
execa then rejects, the existing catch tears down the new disk, and the error reaches the caller instead of the process.
What happened
importDiskpipes the archive read stream without an error listener on the source, andpipe()does not forward errors — so a read failure becomes an unhandled'error'event and kills the daemon.The twin path for the in-container case, at
:1261-1265, names and handles exactly this hazard, so the omission here is inconsistent with the file's own practice.Trigger:
stat(srcPath)at:365succeeds but the read then fails — host disk EIO, or the archive file removed between the stat and the stream open.Expected: the failure reaches the caller honestly, and the
catchat:385-388tears down the half-configured disk ("Leave no half-disk behind the verb's own failure").Got: the read stream's
'error'has no listener, so it becomes anuncaughtException— there is noprocess.on('uncaughtException')anywhere in the server — and the daemon exits. The cleanupcatchnever runs.Rare (needs a host-side fault) and startup reconcile limits the damage afterwards, but the fix is one line.
dor doctor output
Not applicable — defect found by reading the executor; the trigger is a host I/O fault rather than a configuration problem.
Environment
Daemon logs (if relevant)
None captured.
Suggested fix
Mirror the shape already used at
:1265:execathen rejects, the existingcatchtears down the new disk, and the error reaches the caller instead of the process.