Client or integration
Codex CLI
Area
Service lifecycle
Summary
OpenCodex 2.26.0 blocks every native OpenAI request on a systemd-less Linux container when systemctl is present on PATH but the user bus is unreachable. The proxy stays live, /healthz returns 200, and ocx ready reports {"ready":true,"status":"ready"}, but every native request fails locally with HTTP 503 before reaching upstream:
{"error":{"message":"OpenCodex local native-main profile maintenance is active; retry this request","type":"server_error","code":"server_is_overloaded"}}
This is the same admission fence as #1612, but that fix does not cover this environment. #1612 was closed by treating a systemctl spawn failure as absent. In this container systemctl spawns fine — it exits non-zero because there is no user bus:
$ command -v systemctl
/usr/bin/systemctl
$ systemctl --user show opencodex-proxy -p LoadState -p ActiveState -p FragmentPath -p NeedDaemonReload
Failed to connect to user scope bus via local transport: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined
EXIT=1
inspectSystemd() only maps spawnFailed to absent; a non-zero exit still returns unknown, which re-triggers the native-main block. The /.dockerenv marker is present and PID 1 is tini, so this is exactly the externally-supervised foreground shape src/service.ts recommends (Service: unsupported in Docker, "run ocx start directly").
Reproduction
- Debian 13 container (PID 1 =
tini, /.dockerenv present) with systemd installed but no user bus: /run/user/$UID empty, XDG_RUNTIME_DIR and DBUS_SESSION_BUS_ADDRESS unset.
npm install -g @openai/codex@0.148.0 @bitkyc08/opencodex@2.26.0
codex login (ChatGPT), confirm native codex exec works.
ocx start, then ocx sync.
- Send a native request:
$ curl -s -X POST http://127.0.0.1:10100/v1/responses \
-H 'Content-Type: application/json' \
-d '{"model":"gpt-5.5","input":"hi","stream":false}'
{"error":{"message":"OpenCodex local native-main profile maintenance is active; retry this request",...}}
codex exec surfaces this as a misleading message, which is what a user actually sees:
ERROR: Selected model is at capacity. Please try a different model.
ocx restart does not clear it; ocx ready still reports ready:true while every request 503s.
Control flow
systemd installed, no user bus (Docker/tini)
-> inspectSystemd() runs `systemctl --user show` -> spawn SUCCEEDS, exit 1 (no bus)
-> service-manager-probe.ts: !spawnFailed, status !== 0 -> unknown("systemctl show exited 1: ...")
-> ownership-preflight.ts: manager.kind === "unknown" -> ownership: "unknown"
-> server/index.ts: blockNativeMainStartupForUnownedServiceHome("ownership-unknown")
-> native-profile-startup.ts: isNativeMainTrafficBlocked() === true
-> auth-context.ts: throw CodexMainProfileDrainingError -> 503
The #1612 fix (if (shown.spawnFailed) return { kind: "absent" }) sits one line above the branch that fires here.
Verified workaround
Removing systemctl from the proxy's PATH makes the probe hit the spawnFailed path fixed in #1612, and native traffic recovers immediately:
$ mkdir -p ~/ocx-nosysd && for f in /usr/bin/*; do b=$(basename $f); [ "$b" = systemctl ] && continue; ln -sf $f ~/ocx-nosysd/$b; done
$ ocx stop
$ setsid env PATH=$HOME/ocx-nosysd:/usr/local/bin ocx start &
$ curl -s -X POST http://127.0.0.1:10100/v1/responses -H 'Content-Type: application/json' -d '{"model":"gpt-5.5","input":"hi"}'
{"detail":"Input must be a list"} # request reached the handler; no 503
$ codex exec "Reply with exactly: PROXY_OK"
PROXY_OK # tokens used 3,922
Same binary, same config, same login — the only variable is whether systemctl is reachable on PATH. That isolates the probe result as the sole cause.
Setting XDG_RUNTIME_DIR=/run/user/1000 does not help: the directory exists but has no bus socket, so systemctl still exits non-zero ("Failed to connect to user scope bus via local transport: No such file or directory").
Suggested fix
Treat "the question never reached a user bus" the same as an unaskable manager, while keeping fail-closed behavior for real evidence.
- In
inspectSystemd(), classify a no-bus failure as absent rather than unknown. Prefer matching the bus-connection failure specifically (stderr Failed to connect to ... bus), not any non-zero exit.
- Guard it with the container/foreground signal already used elsewhere (
/.dockerenv, PID 1 not systemd), so a real desktop Linux box with a transient bus problem still returns unknown.
- Keep every other path fail-closed: a present unit,
NeedDaemonReload=yes, malformed state, conflicting mirrors, or foreign-home evidence must still yield unknown/foreign.
Regression coverage worth adding:
- Docker +
systemctl present + bus unreachable (exit 1) -> native-main admits traffic.
- Docker +
systemctl present + unit actually installed for a foreign home -> still blocked.
- Non-Docker Linux + bus unreachable -> still
unknown (no widening on real hosts).
Two secondary issues
1. The user-facing error is wrong. A local admission fence is reported to the CLI as ERROR: Selected model is at capacity. Please try a different model. That sends users to change models or wait for quota, when the cause is local and the fix is ocx restore or the PATH workaround. The 503 body is accurate; the CLI-visible mapping is not.
2. ocx ready reports ready while every request 503s. {"ready":true,"status":"ready"} with a 100% failure rate makes readiness unusable as a health signal in exactly the automated/container context where it matters most. Readiness could reflect isNativeMainTrafficBlocked() when native-main is the only configured route.
Also worth noting: ocx status correctly says Service: unsupported in Docker and ocx doctor warns AT RISK after restart (no viable background service; run 'ocx restore'). The product already knows it is in an unsupported-service environment at the moment it blocks traffic for not being able to prove service ownership.
Environment
- OpenCodex 2.26.0 (npm global), Codex CLI 0.148.0
- Debian GNU/Linux 13 (trixie), kernel 6.12.94, x86_64
- Container:
/.dockerenv present, PID 1 = tini, /run/user/1000 empty
- systemd installed (
/usr/bin/systemctl), user bus unreachable
- Bundled Bun 1.3.14 runtime, port 10100
- Auth:
codex login (ChatGPT), native codex exec verified working before ocx sync
Client or integration
Codex CLI
Area
Service lifecycle
Summary
OpenCodex 2.26.0 blocks every native OpenAI request on a systemd-less Linux container when
systemctlis present on PATH but the user bus is unreachable. The proxy stays live,/healthzreturns 200, andocx readyreports{"ready":true,"status":"ready"}, but every native request fails locally with HTTP 503 before reaching upstream:{"error":{"message":"OpenCodex local native-main profile maintenance is active; retry this request","type":"server_error","code":"server_is_overloaded"}}This is the same admission fence as #1612, but that fix does not cover this environment. #1612 was closed by treating a systemctl spawn failure as
absent. In this containersystemctlspawns fine — it exits non-zero because there is no user bus:inspectSystemd()only mapsspawnFailedtoabsent; a non-zero exit still returnsunknown, which re-triggers the native-main block. The/.dockerenvmarker is present and PID 1 istini, so this is exactly the externally-supervised foreground shapesrc/service.tsrecommends (Service: unsupported in Docker, "runocx startdirectly").Reproduction
tini,/.dockerenvpresent) withsystemdinstalled but no user bus:/run/user/$UIDempty,XDG_RUNTIME_DIRandDBUS_SESSION_BUS_ADDRESSunset.npm install -g @openai/codex@0.148.0 @bitkyc08/opencodex@2.26.0codex login(ChatGPT), confirm nativecodex execworks.ocx start, thenocx sync.codex execsurfaces this as a misleading message, which is what a user actually sees:ocx restartdoes not clear it;ocx readystill reportsready:truewhile every request 503s.Control flow
The #1612 fix (
if (shown.spawnFailed) return { kind: "absent" }) sits one line above the branch that fires here.Verified workaround
Removing
systemctlfrom the proxy's PATH makes the probe hit thespawnFailedpath fixed in #1612, and native traffic recovers immediately:Same binary, same config, same login — the only variable is whether
systemctlis reachable on PATH. That isolates the probe result as the sole cause.Setting
XDG_RUNTIME_DIR=/run/user/1000does not help: the directory exists but has no bus socket, sosystemctlstill exits non-zero ("Failed to connect to user scope bus via local transport: No such file or directory").Suggested fix
Treat "the question never reached a user bus" the same as an unaskable manager, while keeping fail-closed behavior for real evidence.
inspectSystemd(), classify a no-bus failure asabsentrather thanunknown. Prefer matching the bus-connection failure specifically (stderrFailed to connect to ... bus), not any non-zero exit./.dockerenv, PID 1 not systemd), so a real desktop Linux box with a transient bus problem still returnsunknown.NeedDaemonReload=yes, malformed state, conflicting mirrors, or foreign-home evidence must still yieldunknown/foreign.Regression coverage worth adding:
systemctlpresent + bus unreachable (exit 1) -> native-main admits traffic.systemctlpresent + unit actually installed for a foreign home -> still blocked.unknown(no widening on real hosts).Two secondary issues
1. The user-facing error is wrong. A local admission fence is reported to the CLI as
ERROR: Selected model is at capacity. Please try a different model.That sends users to change models or wait for quota, when the cause is local and the fix isocx restoreor the PATH workaround. The 503 body is accurate; the CLI-visible mapping is not.2.
ocx readyreports ready while every request 503s.{"ready":true,"status":"ready"}with a 100% failure rate makes readiness unusable as a health signal in exactly the automated/container context where it matters most. Readiness could reflectisNativeMainTrafficBlocked()when native-main is the only configured route.Also worth noting:
ocx statuscorrectly saysService: unsupported in Dockerandocx doctorwarnsAT RISK after restart (no viable background service; run 'ocx restore'). The product already knows it is in an unsupported-service environment at the moment it blocks traffic for not being able to prove service ownership.Environment
/.dockerenvpresent, PID 1 =tini,/run/user/1000empty/usr/bin/systemctl), user bus unreachablecodex login(ChatGPT), nativecodex execverified working beforeocx sync