Skip to content

[Bug][Windows]: ocx update aborts on pending shared teardown when paginated-history restore is refused #4718

Closed

Description

@SeanChengN

Client or integration

OpenCodex dashboard

Area

Installation or packaging

Summary

ocx update aborts on Windows after the service manager has already stopped the proxy when the updater enters the pending shared teardown path and native history restore refuses with history_paginated_requires_native_writer.

This appears to be a regression or uncovered sibling path of #3008. The paginated-history refusal itself is expected and should remain fail-closed. The defect is that the history-only refusal is promoted to a generic stop failure after the service has already stopped, so package replacement never begins.

Expected: if the proxy/service is proven down and the only remaining failure is paginated-history finalization, preserve config/catalog/history/provenance and the backup manifest, warn, and continue package replacement under the same history-only contract introduced for #3008.

Previous non-template report: #4716.

Reproduction

  1. Windows x64 with OpenCodex installed globally through npm and the Windows Task Scheduler service enabled.
  2. Existing paginated Codex history state with a backup manifest/integrity warning already present.
  3. syncResumeHistory is false.
  4. Starting from OpenCodex 2.54.0, run:
ocx update
  1. The updater verifies @bitkyc08/opencodex@2.56.0, stops the service manager, then enters the pending shared teardown path.
  2. Observe:
opencodex v2.54.0 (installed via npm, tag latest)
Verified @bitkyc08/opencodex@2.56.0 integrity metadata sha512-4YXYcCUMG5NUU4sjg…
⏹  Stopping the running proxy before updating...
🛑 Service manager stopped.
↩️  Finishing a shared teardown left unfinished by an earlier stop.
⚠️  Native restore refused: history_paginated_requires_native_writer. Config, catalog, history and provenance were preserved.
opencodex: could not stop the running proxy; aborting the update. Run 'ocx stop' and retry.
  1. Package replacement does not run.
  2. While the service is down, manually install the same target package:
npm install -g @bitkyc08/opencodex@2.56.0
ocx service start
ocx status
ocx doctor
  1. The manual install succeeds and 2.56.0 runs normally.

Current healthy post-upgrade checks:

opencodex 2.56.0
Proxy: running
routing=opencodex-local, service=viable, shim=absent
Codex runtime: codex.exe
Codex version: 0.154.0
OAuth health: ok
ok ocx 2.56.0 matches the running proxy
WHAM reachability: status=200, authenticated
memory usage looks normal

The pre-existing doctor warning remains:

Codex native-write coordinator
ok native-write coordinator not created yet
-- backup manifest or restore target failed integrity checks — manual review required

No history recovery, manifest deletion, SQLite modification, or rollout modification was performed.

Version

2.54.0 -> 2.56.0

Operating system

Windows x64, Windows Task Scheduler service

Provider and model

Not provider-specific

Logs or error output

opencodex v2.54.0 (installed via npm, tag latest)
Verified @bitkyc08/opencodex@2.56.0 integrity metadata sha512-4YXYcCUMG5NUU4sjg…
⏹  Stopping the running proxy before updating...
🛑 Service manager stopped.
↩️  Finishing a shared teardown left unfinished by an earlier stop.
⚠️  Native restore refused: history_paginated_requires_native_writer. Config, catalog, history and provenance were preserved.
opencodex: could not stop the running proxy; aborting the update. Run 'ocx stop' and retry.

Screenshots and supporting files

Related prior issue: #3008

Previous non-template submission: #4716

The important branch-specific marker in this reproduction is:

Finishing a shared teardown left unfinished by an earlier stop.

This suggests the pending-teardown completion path may not preserve the same history-only classification used by the ordinary stop/update path after #3008.

Redacted configuration

{
  "syncResumeHistory": false
}

The Codex history store is paginated and there is an existing backup manifest under the OpenCodex/Codex recovery state. The manifest/integrity warning predates this update attempt.

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
    account-poolOAuth, credentials, Codex pool, quota, failover, plans
    cliCLI, config inject, packaging flags
    installInstallation or packaging
    platformOS/service/tray/ACL (Windows-heavy, not Windows-only)
    serviceService lifecycle (WinSW/launchd/scheduler)
    on Sep 15, 2026
  2. lidge-jun commented on Sep 15, 2026

    @lidge-jun
    Owner

    리뷰 · 우선순위 75 / 80

    이 이슈는 Windows에서 ocx update가 서비스 매니저로 프록시를 이미 멈춘 뒤, 미완료 shared teardown을 마무리하다가 history_paginated_requires_native_writer 거절을 일반 '프록시를 못 멈춤'으로 승격해 패키지 교체를 Abort 하는 버그입니다. 로그에 Finishing a shared teardown left unfinished by an earlier stop. 가 찍히고, 바로 이어 Native restore refused: history_paginated_requires_native_writer 경고 후 could not stop the running proxy; aborting the update 로 끝납니다. 같은 머신에서 서비스가 내려간 뒤 수동 npm install -g + ocx service start는 성공합니다. 관련: #3008(히스토리-only 계약), 이전 비템플릿 #4716.

    현재 dev를 보면 src/config/pending-teardown.ts가 #3008 소유권 영수증이고, src/update/index.ts는 pending teardown이 남아 있으면 stop을 돌린 뒤 decidePostStopUpdate로 proceed/history-only/teardown-outstanding을 가릅니다. history-only면 경고만 하고 설치를 이어가야 합니다. src/codex/history-provider.ts / inject.ts의 history_paginated_requires_native_writer 자체는 fail-closed로 맞고 유지해야 합니다. 문제는 pending shared teardown 완료 경로가 이 거절을 history-only로 분류하지 못하고 일반 stop 실패(proxy-unknown/!proceed)로 떨어지는 쪽입니다. 재현 조건(syncResumeHistory: false, 기존 백업 매니페스트/무결성 경고, 페이지네이션 히스토리)이 구체적이라 회귀 테스트로 고정하기 좋습니다.

    src/update/index.ts decidePostStopUpdate / pending-teardown 분기 - 서비스 정지 후 history-only 거절이 teardown-outstanding 또는 일반 abort로 잘못 매핑되는지 확인.
    src/cli/index.ts shared teardown 완료 - pending receipt를 끝내며 native restore가 paginated refuse일 때 exit/플래그가 update 쪽 history-only와 같은지 맞출 것.
    src/codex/history-provider.ts - history_paginated_requires_native_writer throw/return은 유지(의도된 fail-closed). 고칠 곳은 분류·전파.
    로그 문구 - 이미 서비스가 멈춘 상태에서 'could not stop the running proxy'는 운영자를 오도함. history-only면 #3008과 같은 경고+계속 설치 문구여야 함.
    수동 우회(npm install -g) 성공 - 패키지/무결성 문제가 아니라 updater stop/teardown 계약 문제라는 강한 증거. 회귀 테스트에 'proxy down + paginated refuse + pending receipt' 픽스처를 넣을 것.

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

    너의 추천
    수락. src/update/index.ts + src/cli/index.ts에서 pending shared teardown 완료 시 history_paginated_requires_native_writer를 history-only로 분류해 경고 후 패키지 교체를 이어가게 하고, 회귀 테스트를 추가하는 좁은 PR을 dev에 낸다. 히스토리 거절 자체를 느슨하게 만들지 말 것. Preview deploy는 계획에 없음. #4716이 같은 내용이면 이 이슈로 모으고 닫기.

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

  3. luvs01 commented on Sep 15, 2026

    @luvs01
    Collaborator

    Additional source-level findings from investigating a Windows installation that failed to update from 2.52.0 to 2.56.0:

    The paginated-history containment originated in my #4313 and was carried into the official release through #4342 (merge 10c73569e9141f61c363b5fb61963d5c27e174d9). That merge is an ancestor of the official v2.52.0 tag. This is therefore an integration gap involving our upstreamed protection and the existing stop/update contract, rather than evidence that an unpublished local patch broke this installation. The protection against legacy paginated-history writes must remain.

    There is an important distinction from the ordinary #3008 history-only outcome. At current dev 45cfb04e9757a5a257ab6290d9f24d2ea0bc7573:

    Changing only the exit-code classification to history-only, or deleting pending receipts, would incorrectly claim that shared teardown completed. A preserved config/catalog may still refer to the stopped proxy. Likewise, the updater must retain its liveness and service-respawn checks.

    For the installation investigated, the recovery inspection found the old proxy/update processes absent, no listener on the configured port, three pending teardown receipts, and remaining paginated provider references. The exact original update error was not retained, so this is corroborating state/source evidence rather than a second captured reproduction log. A supported package-only npm install followed by service repair restored operation on 2.56.0; the native Codex config hash remained unchanged, and the history database and pending receipts were not edited.

    A safe fix needs an explicit distinction between package replacement is safe and shared client teardown is complete. If replacement is allowed while restoration is deferred, preserve the unresolved receipts and all protected artifacts, prove the proxy is down and cannot respawn during replacement, and define the restart/failure behavior for clients whose config still targets the proxy. Alternatively, retain the refusal and provide a specific supported package-only recovery path instead of reporting an inability to stop a proxy that is already down.

    Regression coverage should include this all-skipped preflight refusal, genuinely history-only failure after successful config/catalog restoration, client configuration still targeting the proxy, unreadable receipts, and live/unknown proxy or service-respawn states. I have not submitted a code patch that weakens the restore refusal or treats a skipped config/catalog as restored.

  4. added a commit that references this issue on Sep 16, 2026
  5. lidge-jun commented on Sep 16, 2026

    @lidge-jun
    Owner

    Landed via #4746 at fb2ce7d

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

    account-poolOAuth, credentials, Codex pool, quota, failover, plansbugSomething isn't workingcliCLI, config inject, packaging flagsinstallInstallation or packaginglanded-via-maintainerOriginal PR closed after landing via a maintainer merge trainplatformOS/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