Skip to content

[Bug][Windows]: service repair can fail at 20s just before the proxy becomes healthy #3009

Description

@SeanChengN

Client or integration

OpenCodex dashboard

Area

Service lifecycle

Summary

On Windows, ocx service repair can report failure at its fixed 20-second health deadline even though the scheduled service is still starting and becomes healthy immediately afterward.

I saw this while recovering a dashboard update on 2.36.0. The repair command printed that no proxy answered on port 11000 within 20 seconds and returned exit 1. The Task Scheduler job remained running. Shortly afterward, /healthz returned status: ok from the same scheduled startup, and the proxy remained stable.

Expected: a slow but valid Windows cold start should not be reported as a terminal repair failure. A final probe at the deadline, or a slightly longer/phase-aware bounded wait, would avoid the false negative while still failing a service that never binds.

Reproduction

  1. Install OpenCodex 2.36.0 through npm on Windows.
  2. Install the opencodex-proxy Task Scheduler service.
  3. Use an environment where startup work can take around 20 seconds. In this run the service log also showed an NTFS ACL hardening timeout and previous-session journal recovery before the proxy announced its listener.
  4. Run ocx service repair.
  5. Observe the command exit 1 after the 20-second serving check.
  6. Check the scheduled task and /healthz a few seconds later. The same service startup is running and healthy.

Observed command result:

Service repaired, but no proxy answered on port 11000 within 20s.

Follow-up state:

{
  "status": "ok",
  "service": "opencodex",
  "version": "2.36.0",
  "pid": 39388,
  "port": 11000
}

The process was created at 2026-08-30T21:33:19+08:00; the scheduled task run was recorded at 21:33:33+08:00. After it became healthy, repeated checks and the Web UI stayed available. This was not a crash/restart loop.

The current code uses one fixed deadline:

export const SERVICE_INSTALL_HEALTH_MS = 20_000;

and returns failure as soon as that deadline is reached. A final identity probe at the boundary would at least close the narrow race. If 20 seconds is intentionally the normal budget, a separate bounded grace period for a still-running Windows service may be another option.

Related but not duplicate: #720 fixed the GUI update worker's 15-second restart-confirmation boundary. This report is the separate confirmServiceServing() path used by service install/start/repair, which still has a 20-second deadline on current main.

Version

2.36.0; current main still uses the 20-second service-install health deadline.

Operating system

Windows 10 22H2, build 19045, x64

Provider and model

Not provider-specific

Logs or error output

[opencodex] ACL hardening timed out (ETIMEDOUT) — continuing without NTFS ACL harden
Previous session did not shut down cleanly. Codex state restored from journal.
opencodex proxy running on http://localhost:11000

Screenshots and supporting files

Current source: https://github.com/lidge-jun/opencodex/blob/main/src/service.ts#L554-L617

Redacted configuration

{
  "installer": "npm",
  "service": "Windows Task Scheduler",
  "port": 11000
}

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

Activity

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 workingplatformOS/service/tray/ACL (Windows-heavy, not Windows-only)serviceService lifecycle (WinSW/launchd/scheduler)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions