Skip to content

Service: name the holder (PID, liveness, age) when the runtime mutation lease is busy #6492

Closed

Description

@MeroZemory

Area

Service lifecycle

What are you trying to accomplish?

Find out why a supervised Windows proxy won't start when the runtime mutation lease is busy, and decide safely whether the lease is held by a live process or left stale.

What prevents this today?

When ocx start (supervised, via recoverStartStateUnderOwnershipLease) can't get the lease, it fails with only the path:

error: another process owns the runtime mutation lease at %USERPROFILE%\.opencodex\service-state.json.mutation.lock
      at acquireOwnershipMutationLease (src/service/ownership-mutation-lease.mjs:185:40)
      at recoverStartStateUnderOwnershipLease (src/cli/start-owner-fence.ts:12:22)

The Windows wrapper restarts the child every 5 seconds, so service.log fills with this stack. Meanwhile ocx service status only says "OpenCodex proxy not running" and doesn't mention lease contention.

To find the holder you have to open the lock directory and decode the v1-<pid>-<instance>-<token>.json owner file by hand. The obvious shortcut, deleting the lock directory, is unsafe when the holder is still alive. In our case it was alive: an external helper held the lease while waiting for the proxy to start, and the proxy waited on that helper.

What should OpenCodex do?

When lease acquisition times out, put the owner record that readOwner() already parses into the error:

  • holder PID, and whether that PID is alive
  • lease age (createdAt / owner file mtime)
  • if available cheaply, the holder's image name

Optionally, ocx service status / doctor could also report "runtime mutation lease held by PID N for Ns" while the lock exists.

Example usage or interface

error: another process owns the runtime mutation lease at …\service-state.json.mutation.lock
       (holder pid 6236 [alive, python.exe], held 212s; stale leases are reclaimed after <STALE_MS> once the holder exits)

Alternatives or workarounds

Read the owner JSON in the lock directory by hand and check the PID with Get-Process. This works, but it isn't discoverable from the error message.

Additional context

Related but different: #5760, an updater deadlock on its own mutation lease, fixed in #5856. Here the holder is outside OpenCodex, so OpenCodex can't avoid the wait, but it can name who it is waiting for.

Version 2.76.0, Windows 11 x64. The same code is on dev.

Checks

  • I searched existing issues and documentation.
  • This request describes a concrete OpenCodex workflow rather than merely naming a desired technology.
  • I removed secrets and personal data.

Activity

  1. Ingwannu commented on Oct 4, 2026

    @Ingwannu
    Owner

    Tracked by #6512, which adds a read-only holder status/error projection and preserves stale-lock recovery rather than deleting a live holder. I read its current five-file diff at 74d59b8; the focused tests explicitly retain the stale owner file on inspection. This is not merged or verified on your Windows service yet, so the issue remains open. PID/image/age are diagnostics, not permission to kill the process or manually delete its lease. No installed service or lock was changed here.

  2. added a commit that references this issue on Oct 4, 2026
    815b1f6
  3. lidge-jun commented on Oct 4, 2026

    @lidge-jun
    Owner

    Fixed on dev by #6512 (815b1f6): a busy runtime mutation lease now reports the recorded holder (PID, liveness, age). Closing manually because PRs target dev; it ships in the next release.

  4. added a commit that references this issue on Oct 7, 2026
    5b3f78a
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

    enhancementNew feature or requestserviceService lifecycle (WinSW/launchd/scheduler)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions