Skip to content

[Bug]: Windows ocx service repair prints success and failure (exit code 199) after a 2-minute elevated re-registration while the proxy is down #4914

Closed

Description

@Awesom-Jack

Client or integration

Codex App

Area

Service lifecycle

Summary

On Windows, ocx service repair (2.57.0) run against a Task Scheduler service that 2.48.0 had installed ran for 2 min 08 s, then printed a success line and a failure line for the same run:

  • stdout: ✅ opencodex service repaired and serving on port 10100.
  • stderr: ❌ Service repair failed: Background service install failed with exit code 199.

Nothing listened on port 10100 while it ran, so every Codex App request failed for about 2 minutes. When it finished, the task definition returned by schtasks /query /tn opencodex-proxy /xml was identical to the one before the repair (apart from blank lines), and the service was healthy: /readyz reported ready with version 2.57.0, and ocx service status printed ✅ service installed (Task Scheduler).

Expected: a single, truthful outcome. If the elevated re-registration does not complete and the existing definition is restarted, say so, for example with a warning that the registration was kept. Do not report success and failure together. The elevation wait should also not keep the proxy down, for example by asking for elevation before the task is stopped.

Context from reading src/service/repair.ts, which is identical on dev at 5061f2c95:

  • repairService calls stopWindows() before reregisterWindowsSchedulerTask, so the port stays closed for as long as the elevated fallback waits.
  • The existing task was created without elevation by ocx service install 2.48.0 (RunLevel LeastPrivilege, LogonType InteractiveToken, Priority 4). Its triggers name the account (<UserId>MACHINE\user</UserId>) instead of the SID. My guess is that this triggered identityUpgradeNeeded and the re-registration. I have not verified this.
  • Exit code 199 is neither OCX_ELEVATED_UAC_CANCELLED (1223) nor OCX_ELEVATED_PROTOCOL_FAILED (13), and I could not find where it comes from. Nobody was at the console, so a UAC prompt, if one appeared, went unanswered. consent.exe was no longer running afterwards.

Reproduction

Observed once. I did not repeat it to avoid a second outage.

  1. On Windows 10 22H2, as a standard user with UAC enabled: npm install --prefix D:\ocx\runtime @bitkyc08/opencodex@2.48.0, then ocx service install (Task Scheduler backend).
  2. End the service process tree (wscript → cmd → bun), then replace D:\ocx\runtime with a 2.57.0 install at the same path.
  3. With the same OPENCODEX_HOME and CODEX_HOME, run ocx service repair and leave the console unattended.
  4. Result: about 2 minutes with port 10100 closed, then both lines above. The registered task XML is unchanged, and the service runs 2.57.0.

In step 2 I stopped the processes myself before running repair. Repair's own flow ends the task first (stopWindows), so the outage should match without that manual step.

Version

2.57.0 (repair), on a service installed by 2.48.0. Bundled Bun 1.4.0.

Operating system

Windows 10 22H2 (10.0.19045)

Provider and model

Not provider-specific (the proxy routes openai / gpt-5.6-sol and zai / glm-5.3).

Logs or error output

[2026-09-17T16:44:57.471Z] ocx service repair started (ocx.cmd, 2.57.0)
[17/09/2026 18:47:02,68] opencodex service wrapper start          <- service.log, local time = 16:47:02Z
[2026-09-17T16:47:05.553Z] stdout: ✅ opencodex service repaired and serving on port 10100.
[2026-09-17T16:47:05.553Z] stderr: ❌ Service repair failed: Background service install failed with exit code 199.

The process exit code of ocx.cmd was not captured (PowerShell Start-Process -RedirectStandardOutput returned a null ExitCode).

Checks

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

Activity

  1. added
    bugSomething isn't working
    cliCLI, config inject, packaging flags
    installInstallation or packaging
    platformOS/service/tray/ACL (Windows-heavy, not Windows-only)
    serviceService lifecycle (WinSW/launchd/scheduler)
    on Sep 17, 2026
  2. lidge-jun commented on Sep 17, 2026

    @lidge-jun
    Owner

    리뷰 · 우선순위 70 / 80

    이 이슈는 제품 패치 PR이 아니라 Windows ocx service repair의 결과 보고·다운타임 버그 리포트다. 보고 환경은 2.48.0이 설치한 Task Scheduler 서비스 위에 2.57.0 repair를 돌린 경우다. 지금 로컬 dev tip은 4655d32f8(패키지 2.59.0)이고, 본문이 가리킨 src/service/repair.ts 흐름은 tip에도 그대로 있다. 재현은 한 번뿐이라고 했고, 고의로 반복하지 않았다.

    관찰된 증상은 세 겹이다. (1) 약 2분 동안 포트 10100에 아무도 안 듣고 Codex App 요청이 전부 실패. (2) 같은 실행에서 stdout에 성공 줄(repaired and serving)과 stderr에 실패 줄(Background service install failed with exit code 199)이 같이 찍힘. (3) 끝나면 태스크 XML은 거의 그대로이고 서비스는 2.57.0으로 healthy. 기대는 ‘성공·실패를 동시에 말하지 말고, elevation이 끝날 때까지 프록시를 죽이지 말라’는 쪽이다.

    코드 쪽과 맞는지 보면, repairService는 Windows에서 먼저 stopWindows()를 호출한 뒤(repair.ts 근처 196행) identity/priority upgrade가 필요하면 reregisterWindowsSchedulerTask로 올린다. 재등록이 실패하면 예전 정의를 다시 시작하고 원래 에러를 다시 던지는 보존 프로토콜이 있다(204–298행 주석·catch). 그 다음 CLI(cli.ts 204–217행)는 의도적으로 실패를 찍은 뒤에도 reportServiceServing을 호출한다. #4236 결함 1f를 막으려고 ‘실패 + 지금 듣고 있는지’ 둘 다 보여 주는 설계다. 그래서 성공·실패가 같이 보이는 현상은 리포터가 본 그대로이고, 동시에 ‘버그처럼 보이는 UX’이기도 하다.

    exit code 199는 OCX_ELEVATED_* 상수(0/10–14/1223)에 없다. 무인 콘솔에서 UAC가 안 받아지면 1223이 나와야 하는데 199가 나온 점은 리포터 말대로 미해결이다. ELEVATION_REQUEST_TIMEOUT_MS = 120_000은 약 2분 다운타임과 맞는다. identityUpgradeNeeded 가설(계정명 UserId → SID, Priority)도 tip의 identityUpgradeNeeded / priorityUpgradeNeeded 분기와 방향이 같다. 다만 그 한 번의 실행에서 실제로 그 분기를 탔는지는 로그에 없다.

    types.ts/config.ts 스플릿 캠페인과는 무관하다. 닫을 중복 이슈로 보이지도 않는다. 우선순위는 ‘성공·실패 이중 보고 UX’보다 ‘stop → elevate 대기 동안 포트가 비는 다운타임’이 더 세다. 2.58.0 트레인(#4915 프로모션) 밖 잔여로 두는 편이 맞고, 픽스 PR이 오면 stop 순서·메시지 단일화·199 출처를 같이 봐야 한다.

    경로 src/service/repair.ts · repairService - stopWindows 후 reregister; 실패 시 기존 정의 재시작·에러 재throw. 다운타임·보존 경로와 맞다.
    라인 196 - stopWindows()가 elevate/reregister보다 앞. 리포터가 말한 ‘elevation 끝날 때까지 포트 닫힘’과 일치.
    라인 171–177 - identityUpgradeNeeded / priorityUpgradeNeeded. 레거시 계정명·Priority 7 가설과 맞닿음. 이번 재현에서 실제로 true였는지는 미확인.
    경로 src/service/cli.ts · 204–217 - 실패 console.error 후 reportServiceServing. 이중 메시지·exitCode=1 유지가 의도된 동작.
    경로 src/lib/windows-elevation.ts - ELEVATION_REQUEST_TIMEOUT_MS=120000; OCX_ELEVATED_*에 199 없음. 199 출처는 추가 조사가 필요.
    경로 src/service/windows-scheduler.ts · Background service install failed - exitCode를 메시지에 실어 throw. stderr 문구와 일치.

    메인테이너의 판단이 필요한 지점

    너의 추천
    이슈는 열어 둔다. 다음 픽스 PR은 (1) stop→elevate 순서 재배치 또는 elevate 전 사전 승인, (2) 실패 후 serving이면 성공 체크 대신 ‘등록 유지·서비스 복구됨’ 경고 한 줄, (3) 199를 OCX 상수/매핑 표에 올리거나 원인 메시지를 붙이는 쪽을 같이 보자. types/config 스플릿이나 2.58.0 프로모션(#4915) 이유로 이 이슈를 닫지 않는다.

    이 댓글은 grok-bot이 작성했습니다

  3. lidge-jun commented on Sep 18, 2026

    @lidge-jun
    Owner

    Fixed on dev by #4967, squashed as 46116473d2a72372d0553559a9bd11ca5d15c6aa.

    You were right that the checkmark was the false half. The two lines came from two different statements: src/service/cli.ts printed the failure in its catch and then called reportServiceServing unconditionally, and that function's success line asserts the operation happened. The elevated re-registration never completed, the recovery path restarted the definition that was already installed, and your observation that the registered task XML came out unchanged apart from blank lines matches that exactly.

    What did not change, and why: running the probe after a throw is deliberate and stays. A rollback inside installLaunchd, or the Windows preserve-and-restart protocol, can genuinely leave the previous job answering, and an operator needs that fact rather than a bare failure — that is #4236, defect 1f. The defect was never the probe; it was that its answer arrived as a second, contradictory outcome. The failure now travels into the report, and no branch prints a checkmark when the operation failed.

    Shipping in the next release off dev.

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 workingcliCLI, config inject, packaging flagsinstallInstallation or packagingplatformOS/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