Skip to content

[Bug]: dev-electron supervisor survives its parent and keeps restarting Electron #19109

Closed

Description

@renepf

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/desktop

Steps to reproduce

  1. Start the desktop dev app from a checkout: vp run dev:desktop --home-dir <some dev home>.
  2. Kill the parent vp process without letting it forward a signal — kill -9 <vp pid>, or close
    a terminal that dies before it can signal its children.
  3. Collect the supervisor PIDs and check their parent:
    ps -o pid=,ppid=,command= -ax | grep 'dev-electron.mjs'
    
  4. Touch one of the watched build artifacts: touch apps/desktop/dist-electron/main.cjs.
  5. Repeat steps 1 and 2 a few times without cleaning up in between.

Expected behavior

This is the maintainers' call. Two directions, offered for discussion rather than as a proposal:
have the supervisor exit when its parent goes away, and/or extend cleanupStaleDevApps() to reap
stale supervisors of the same dev root as well as their apps.

Actual behavior

apps/desktop/scripts/dev-electron.mjs handles SIGINT, SIGTERM and SIGHUP and shuts down
cleanly (:261-269). It has no parent-death watch, so when the parent vp process dies without
forwarding a signal the supervisor is reparented to ppid 1 and keeps restarting Electron on the
next file change (:188-202, debounce :50).

cleanupStaleDevApps() (:92-100, called at startup on :258 and twice inside stopApp(), at
:168 and :177 — so on every debounced restart via :197, not only on shutdown via :247)
only clears stale Electron apps of the same dev root, via
pkill -f -- --t3code-dev-root=<desktopDir>. It does not clear stale supervisors. Several
orphans therefore coexist, each restarting Electron and each killing the others' window on its own
startup, all against the same T3 home.

Stopping the three orphans by their captured PIDs let the next run start cleanly with the same
database: POST /oauth/token returned 200 once and zero SessionBootstrapError.

The 401 that surfaces while orphans are running is filed separately as #19110: this issue is
the stale process, that one is why the symptom is undiagnosable.

One note while reading :97: that line uses pkill -f with the worktree path as the pattern,
which is the exact shape AGENTS.md forbids contributors in "The three ways to hurt yourself",
point 1 ("Your own agent process has this worktree's path in its argv"). Whether the script itself
should be held to that rule is a separate question; flagging it because an agent that reads
AGENTS.md and then this script gets contradictory guidance.

Impact

Major degradation or frequent failure

Version or commit

7b6d907

Environment

macOS 26.3.2 (Darwin 25.3.0), Apple Silicon; Node 24.13.1; pnpm 11.10.0; vp 1.1.0 — the global
install resolved from the bare vp in step 1 (command -v vp → /opt/homebrew/bin/vp,
vp --version → vp v1.1.0). The checkout also ships its own ./node_modules/.bin/vp, which
reports vp v1.0.0; that one was not used for this run.

Logs or stack traces

$ ps -p <pid> -o ppid=
# three `node .../dev-electron.mjs` processes, each reporting ppid 1

# after stopping those three by their captured PIDs, same run, same database:
#   POST /oauth/token  -> 200   (1 occurrence)
#   SessionBootstrapError -> 0 occurrences

Workaround

Before each start, check that no dev-electron.mjs is running and that the dev ports are free,
and stop a run by the PID of the vp process plus the supervisor PIDs collected at startup.

Activity

  1. juliusmarminge commented on Oct 13, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Confirmed on main. This only affects the desktop dev workflow (dev:desktop), not shipped builds. Production backend orphaning is tracked separately in #13747.

    What main does in apps/desktop/scripts/dev-electron.mjs:

    • The supervisor only exits on SIGINT/SIGTERM/SIGHUP (:261-269). Nothing watches for parent death, so after a kill -9 of vp it is reparented to PID 1, and the next file change still runs scheduleRestart() (:183).
    • cleanupStaleDevApps() (:92-100) only runs pkill -f -- --t3code-dev-root=…, which matches Electron apps and not other supervisors. Orphaned supervisors therefore pile up and fight over the same T3 home. [Bug]: desktop dev: stale backend produces an HTTP 401 on /oauth/token with no actionable cause #19110 is the 401 this causes.

    The workaround is in the report: before restarting, kill any leftover dev-electron.mjs processes.

    Closed PR #8736 already addresses the root cause. It moves the supervisor under dev-runner as a sibling process group and drops the pkill -f cleanup. It was closed during a stale-PR sweep and not on its merits, so it's the likely starting point for a fix. Keeping this open as a dev-tooling bug.

  2. added
    acceptedfeature request accepted
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    on Oct 13, 2026
  3. added
    needs more infoInitial triage showed no bug. Awaiting more info
    and removed
    needs more infoInitial triage showed no bug. Awaiting more info
    on Oct 22, 2026
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

    acceptedfeature request acceptedbugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions