Skip to content

[Bug]: Remote Link Child keeps serving after its durable client record disappears, and disconnect cannot recover it #8243

Closed

Description

@lidge-jun

Client or integration

Codex CLI

Area

Service lifecycle

Summary

A Remote Link Child can keep serving as a connected client from an in-memory connection snapshot after its durable client record has disappeared from config.json. The Home sees the tunnel as connected, the relayed catalog matches, and the Child's /readyz reports link: available, but every CLI on the Child reads ocx connect status --json as disconnected. The Home's pinned ocx sync --expect-link <id> is therefore refused with child-link-mismatch:disconnected (exit 5) on every run.

The supported recovery path also fails: the Child refuses ocx disconnect (and GOAT's re-link, which disconnects first) because there is no client record to tear down, while the link token and the running client runtime remain. The machine is stuck until someone hand-cleans state.

Expected: either the runtime notices its durable record is gone and stops serving as a client (or reports the divergence in status/readyz), or ocx disconnect can tear down an orphaned link token and runtime so the Home can re-link.

Reproduction

Observed on a macOS Child (Desktop 2.93.0):

  1. Child linked to a Home; Desktop runtime started on Oct 28 and kept running.
  2. On Nov 4 the default ~/.opencodex/config.json was replaced (writer not yet identified); it now has neither client nor runtimeRole. No pending-connect marker.
  3. Child GET /healthz reports role: client, same PID as before; GET /readyz reports status: ready, link.state: available.
  4. Child ocx connect status --json (both the Desktop shim and the app-bundled CLI): state: disconnected.
  5. Home ocx sync --json: that Child skipped as child-link-mismatch:disconnected, exit 5 from the remote command; overall exit 0.
  6. Re-link through disconnect: Child refuses the connection change.

Source anchors: src/client/runtime.ts reads connected state once at startup and passes the snapshot to the listener; src/client/machine-listener.ts retains it and /readyz reports availability rather than durable ownership; src/client/state.ts readClientConnectionState returns disconnected for a config with no client/role; src/client/sync-expectation.ts correctly refuses on that verdict.

Version

Child 2.93.0 (Desktop); Home 2.97.0; source checked at dev 553a621

Operating system

macOS (Child and Home)

Provider and model

No response

Logs or error output

Home ocx sync --json child row:
{"linkId":"lnk_…","state":"skipped","reason":"child-link-mismatch:disconnected","exit":5}
Re-link: disconnect step failed: refused the connection change

Screenshots and supporting files

No response

Redacted configuration

{"runtimeRole": "<absent>", "client": "<absent>"}

Checks

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

Activity

  1. github-actions commented on Nov 6, 2026

    @github-actions
    Contributor

    Automated translation bookkeeping — detected language: English.

  2. lidge-jun commented on Nov 6, 2026

    @lidge-jun
    OwnerAuthor

    Part 1 landed on dev via #8249 (cdb64a9): a Remote Link Child now reports client_state_changed in readiness and status when its saved connection no longer matches the runtime startup snapshot. The operator recovery path and the ocx config import guard are in #8253 (security review in progress). Keeping this issue open until that lands.

  3. lidge-jun commented on Nov 7, 2026

    @lidge-jun
    OwnerAuthor

    Fixed on dev by #8249 (cdb64a9: readiness/status report client_state_changed when the saved connection no longer matches the runtime) and #8253 (ebeb1dc: operator-confirmed ocx disconnect --orphaned-token --yes moves an orphaned link token into a private backup, refusing on a Hub, non-loopback binds, admission credentials or installed services; ocx config import no longer replaces a connected client record). Security review passed.

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 workingserviceService lifecycle (WinSW/launchd/scheduler)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions