openclaw / openclaw/openclaw

[Bug]: Codex configuration refresh skips unsubscribe when retained owner is missing

Open
#153,003 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

clawsweeper:fix-shape-clear clawsweeper:queueable-fix clawsweeper:source-repro impact:session-state issue-rating: 🦞 diamond lobster no-stale P2
Dominant language
TypeScript
Stars
390k
Forks
82k
PR merge metrics
PR metrics pending

Description

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

An ordinary Codex configuration refresh can skip physical unsubscribe when its local retained-owner record is absent, causing an otherwise idle thread to fail the unload-confirmation guard.

Steps to reproduce

Deterministic repository-harness reproduction on release v2026.9.5:

  1. Use the real leased app-server wire client fixture in extensions/codex/src/app-server/thread-lifecycle-policy-refresh.test-support.ts.
  2. Start a thread through startOrResumeThread with initial developer instructions. Keep its physical connection subscribed and its durable binding, but omit the process-local retainCodexAppServerLiveThread registration.
  3. Have thread/read report idle. Model the upstream protocol by emitting thread/status/changed: notLoaded during override resume only after the connection unsubscribed and no other subscriber remains.
  4. Resume through startOrResumeThread with replacement developer instructions.
  5. On the unmodified release, the missing-owner regression fails with Codex did not confirm unloading its previous configuration: the physical unsubscribe was skipped.

This explicitly constructs the missing-retention state. The production action that creates that state has not been conclusively attributed.

Expected behavior

Reconcile the exact bound connection's subscription before configuration refresh. Preserve the unload-confirmation guard and reject changes when another subscriber prevents cold rebuilding. Do not send duplicate unsubscribes after an acknowledged release.

The existing retained-owner path and inspected Codex rust-v0.154.0 idle/unsubscribed override-resume contract provide the reference behavior.

Actual behavior

The ordinary resume callback discards the failed retained-release result. The native thread stays subscribed, override resume preserves its loaded configuration, and OpenClaw refuses the turn because no notLoaded notification was observed.

OpenClaw version

2026.9.5; isolated source ec9c1a13db8938e5a3eaa51fca2e981cde2395a9.

Operating system

Ubuntu 26.04.1 LTS.

Install method

Affected npm installation; reproduction and candidate validation in an isolated pnpm release checkout.

Model

Model-independent synthetic app-server wire fixture; no inference required for this reproduction.

Provider / routing chain

OpenClaw Codex harness -> leased app-server protocol fixture. Separate protocol probes used installed Codex 0.154.0.

Logs

Baseline + missing-retained-owner regression:
Codex did not confirm unloading its previous configuration

Candidate validation:
thread-lifecycle.binding.test.ts: 247/247 passed
client-runtime.test.ts: 43/43 passed

Screenshots, recordings, and evidence

A local candidate records acknowledged per-connection release/resubscribe facts and only performs the untracked fallback after observing a loaded thread without a known successful release. Verification includes missing-owner recovery, sibling-subscriber refusal, native identity preservation, and 100 rounds across eight owners with exactly 800 unsubscribes. Extension typecheck passed; repository autoreview was scoped-clean at P1. The candidate is not installed or released.

Source boundaries: ordinary resume, bound release.

Impact and severity

The reproduced edge case blocks resuming an idle bound session with updated configuration. Similar guard errors were observed across several production sessions, but per-turn attribution to this exact missing-retention state remains unproven. No data loss is established.

Additional information

Related but distinct: #143187 concerns stale cleanup deleting a successor binding; #148837 concerns settled systemError. The broader reload/catalog outage reported in #152275 is not proven to be fixed by this candidate. Do not remove the unload guard or assume that a blind delay repairs this ownership issue. Introducing commit and last-known-good version: NOT_ENOUGH_INFO.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the ordinary resume path in extensions/codex/src/app-server/thread-lifecycle-run.ts and the bound release path in extensions/codex/src/app-server/thread-lifecycle-warm.ts, then inspect the real wire-client fixture named in the reproduction. Use thread-lifecycle.binding.test.ts and client-runtime.test.ts to verify missing-owner recovery, subscriber refusal, identity preservation, and unsubscribe counts while preserving the unload-confirmation guard.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
44/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.