Skip to content

Windows host: daemon never becomes reachable (0.21.23) #3291

Description

@riptone

Environment

  • agent-device 0.21.23 (latest), installed as a devDependency and run with npx agent-device
  • Windows 11 Pro 10.0.26200 (native host, not WSL)
  • Node.js 26.7.0
  • Android SDK emulator 35 (WHPX), adb from the Windows platform-tools

Description

On a native Windows host the daemon never becomes reachable, so every command fails with
COMMAND_FAILED: Failed to start daemon. There are two separate causes:

  1. EPERM in truncateDaemonLog (src/daemon-registration-owner.ts). The log is opened
    with flag 'a' and then emptied with fs.ftruncateSync. On Windows a handle opened for
    append only cannot be truncated, so the daemon exits:
    Daemon error: EPERM: operation not permitted, ftruncate.
    Creating the file with 'a' and then truncating through a handle opened with 'r+' fixes
    this: the daemon starts and listens.

  2. Live daemon reported as not-running. With (1) patched, the daemon is listening
    (netstat shows it on the port in daemon.json), but the client still reports
    startError: daemon process … exited before readiness and "termination": {"status": "not-running"}.
    It then logs Daemon registration busy; exiting. on every retry. Process identity in
    owner-identity.js relies on ps -ax -o pid=,ppid=,command= / lstart, which do not exist
    on Windows, so ownership can never be verified.

Not a regression as far as I can tell: the docs never state Windows host support. Previous
Windows fixes (#2022, #2526, #502) suggest it is intended to work.

Reproducible Demo

On native Windows 11:

npm i -D agent-device@0.21.23
npx agent-device doctor --debug

Result: Failed to start daemon; ~/.agent-device/daemon.log shows the EPERM from (1). After
patching (1), the same command shows the daemon listening while the client reports it as
not-running, which is (2).

Activity

  1. thymikee commented on Oct 9, 2026

    @thymikee
    Member

    Thanks for the report. Two separate causes, and the first is a quick fix:

    1. Log truncation (fixing first): src/daemon-registration-owner.ts opens the daemon log for append and then truncates it through that handle, which fails with EPERM on Windows. That alone stops the daemon from starting, and it's independent of the second cause.
    2. Process identity: daemon ownership is checked with ps / lstart, which Windows doesn't have. That's being replaced with a single cross-platform approach (see macOS sandbox blocks ps-backed recording process identity #2376).
  2. thymikee commented on Oct 9, 2026

    @thymikee
    Member

    Correction to my triage comment above — point 2 pointed the Windows identity work at the wrong issue, so let me set the record straight:

    1. Both fixes land in fix(daemon): make the daemon reachable on native Windows hosts (#3291) #3330; neither is waiting on anything. The log-truncation fix and the Windows process-identity branch ship together there: host-process.ts answers birth, CommandLine, and liveness from a single PowerShell CIM (Win32_Process) query at the existing host-process seam, with a platform split so POSIX behavior is byte-identical to main. My earlier sentence claiming identity was "being replaced with a single cross-platform approach (see macOS sandbox blocks ps-backed recording process identity #2376)" was wrong.

    2. macOS sandbox blocks ps-backed recording process identity #2376 is not the successor to this fix. It is the macOS-sandbox problem — /bin/ps execution refused under the sandbox, answered by a native proc_pidinfo(PROC_PIDTBSDINFO) + sysctl(KERN_PROCARGS2) probe for simulator-recording ownership — and its required behavior explicitly keeps non-macOS behavior unchanged. It never mentions Windows. It is a sibling at the same host-process seam, not a prerequisite for fix(daemon): make the daemon reachable on native Windows hosts (#3291) #3330.

    3. The Windows identity path has live evidence. An external tester ran the full checklist on native Windows 11 (10.0.26200, Node 24.21.0 + Electron 44.4.2, both transports) at fix(daemon): make the daemon reachable on native Windows hosts (#3291) #3330 head a7821ef58: clean start with zero EPERM, a processStartTime matching the daemon pid's CIM CreationDate exactly, daemon reuse, graceful stop — plus a non-ASCII-path round-trip, and a 0.21.12 baseline on the same host still failing. Details in fix(daemon): make the daemon reachable on native Windows hosts (#3291) #3330 (comment).

    Housekeeping: I am dropping the ready-for-agent label I applied during triage — with the fix PR open, green, and awaiting human review, leaving this in an agent queue invites duplicate work on a fixed bug. State lives on #3330 (ready-for-human) until a maintainer merges; #3330 says Refs #3291, so closing this issue stays the maintainer's call.

  3. IGx89 commented on Oct 9, 2026

    @IGx89

    Just ran into this myself. 0.21.20 works well on Windows but 0.21.21-23 do not.

  4. thymikee commented on Oct 9, 2026

    @thymikee
    Member

    Fixed on main by #3330 (87c5b3b): the daemon log is now truncated through a handle that permits ftruncate on Windows, and process identity (start time, command line, liveness) is read from a PowerShell CIM Win32_Process query instead of ps.

    This isn't in a release yet — 0.21.21–0.21.23 still have the bug, and the fix will ship in the next release after 0.21.23. Until then, 0.21.20 is the last version that works on native Windows.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions