Windows flake: daemon-foreground-relaunch e2e cleanup hits ENOTEMPTY while the unawaited stop CLI still writes the state dir
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 76/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- github-actions, javascript, node.js
Research direction
Start with test/core/daemon-foreground-relaunch.test.js around line 282 and compare cleanup retries in test/core/daemon.test.js and test/core/daemon-backfill-sweep-wiring.test.js. Keep and await the Windows stop child before gateway assertions and cleanup, and ensure it is stopped if cleanup runs first. Done when the test passes repeatedly on Windows and test-windows is green.
Written by the indexing model from the issue text.
Description
Symptom
On test-windows, test/core/daemon-foreground-relaunch.test.js:282 ("an unsupervised daemon run applies a staged central config and keeps the gateway answering") sometimes fails after every assertion has passed. The cleanup fs.rm(root, { recursive: true, force: true }) in the finally block throws:
[Error: ENOTEMPTY: directory not empty, rmdir 'C:\Users\RUNNER~1\AppData\Local\Temp\hyp-t-2puvEe\hyp-relaunch-e2e-eWyA2J\.hyp\hypaware'] { errno: -4051, code: 'ENOTEMPTY', syscall: 'rmdir' }
There were three sightings on 2026-11-06. Each one passed when the failed job was re-run once:
| PR | Run | Head | Directory that would not empty |
|---|---|---|---|
| #2913 | 42136275812 | 715c1cbb | .hyp\hypaware |
| #2914 | 42139698957 attempt 1 | 3ac79c02 | .hyp\hypaware\dev-telemetry |
| #2916 | 42142432583 attempt 1 | 20dad66b | .hyp\hypaware |
None of these PRs touched the daemon or this test. Under the test-windows landing gate, every sighting costs a re-run before a PR can land.
Likely cause
On win32 the test stops the daemon through the LLP 0300 file control channel. It spawns hyp daemon stop and does not keep a handle on that process:
if (process.platform === 'win32') {
spawn(process.execPath, [path.join(REPO_ROOT, 'bin', 'hypaware.js'), 'daemon', 'stop'], { env, stdio: 'ignore' })
}
The test then waits only for the daemon to exit before fs.rm runs. The stop CLI is a second process with the same HYP_HOME and HYP_DEV_TELEMETRY=1. requestDaemonStop (src/core/daemon/runtime.js) polls until the daemon's pid is gone. Only after that does the CLI:
- reconcile the pid files under the state root;
- print
daemon: stopped; - flush its own dev telemetry into
<HYP_HOME>/hypaware/dev-telemetry(src/core/observability/logger.js,meter.js,tracer.js); - exit. That work overlaps the recursive delete:
- Windows rmdir fails with ENOTEMPTY when an entry is created while the delete is running;
- it also fails when a file is still open by a live process.
The #2914 sighting failing on dev-telemetry itself supports this reading. POSIX never hits the race because it stops the daemon with proc.kill('SIGTERM') in-process.
Proposed fix (test-only, bounded)
- Keep the stop child and await its
exitbefore the gateway assertions and the cleanup. If it is still alive whenfinallyruns, kill it. - Give the cleanup the bounded retry the sibling daemon tests already use:
fs.rm(root, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }). Examples aretest/core/daemon.test.js:956andtest/core/daemon-backfill-sweep-wiring.test.js:139. That bounds the wait at about 1s worst case. Step 2 alone would hide the race rather than close it, so step 1 is the fix and step 2 is the backstop.
No product code changes. The stop CLI tidying pid files and flushing its telemetry after the daemon exits is the correct order.
Validation
Windows is gated by LLP 0584 #validation, and test-windows is a landing gate. The fix is proven by a green test-windows on the fixing head, plus the test passing in a loop on a Windows runner. Linux and macOS are unaffected because they take the SIGTERM path.
Logs from the three runs are held in the HypForge review records for #2913, #2914 and #2916.
- Dominant language
- JavaScript
- Stars
- 11
- Forks
- 0
- Avg merge
- 2h 15m
- Merged PRs (30d)
- 322
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from hyparam/hypaware
-
Windows flake: withFileLock throws EPERM when the previous holder's lock file is still being deletedOpen
Difficulty 2/5 1-3 hours Newbie friendliness 79/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
hyparam/hypaware#2922 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
docs: ollama.md says --source ollama adds to an existing install, but without --force it refusesOpen
Difficulty 2/5 Under an hour Newbie friendliness 62/100
Maintainers usually reply within 1 day
All issues in hyparam/hypaware
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
-
area: agent area: integration lane: strong-agent priority: P2 roadmap size: S type: integration type: task
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
arminazimi/seaworthy#688 ·
Maintainers usually reply within 1 day
-
idea-scout idea:245
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
jeanibarz/agent-notebook#245 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
obsidianmd/obsidian-developer-docs#281 ·
Maintainers usually reply within 4 days
-
Convert Mosaic Widget to TypeScriptPossibly taken @dangotbanned claimed this today. Openjavascript widget
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
Maintainers usually reply within 1 day