`codex app-server daemon` commands fail with `path must be shorter than SUN_LEN` when CODEX_HOME is a deep path (macOS)
Summary
All codex app-server daemon client commands (version, start, stop, ...) derive the control socket path as $CODEX_HOME/app-server-control/app-server-control.sock. On macOS, the sun_path limit for Unix domain sockets is 104 bytes, so any CODEX_HOME longer than ~60 characters makes these commands fail before they can connect:
Error: failed to connect to <CODEX_HOME>/app-server-control/app-server-control.sock
Caused by:
path must be shorter than SUN_LEN
There is currently no way to override the control socket location for the daemon client commands: codex app-server proxy accepts --sock, and the server side accepts --listen unix://PATH, but codex app-server daemon version/start/stop do not, and there is no config key or environment variable for it (the path is hardcoded in app_server_control_socket_path() in codex-rs/app-server-transport/src/transport/mod.rs).
Deep CODEX_HOME paths are common for tools that run Codex in isolated per-task or per-project homes (CI sandboxes, agent platforms, devcontainer setups), where the home lives inside a nested workspace directory and easily exceeds the budget.
Environment
- macOS (Darwin 25.4.0, arm64)
- codex-cli 0.137.0 (also reported on 0.139.0)
Reproduction
DEEP="/tmp/codex-sunlen-repro/$(printf 'a%.0s' {1..40})/$(printf 'b%.0s' {1..40})/codex-home"
mkdir -p "$DEEP"
echo "${#DEEP}" # 116 chars
CODEX_HOME="$DEEP" codex app-server daemon version
Output:
Error: failed to connect to /private/tmp/codex-sunlen-repro/aaaa…aaaa/bbbb…bbbb/codex-home/app-server-control/app-server-control.sock
Caused by:
path must be shorter than SUN_LEN
Note that pointing CODEX_HOME at a short symlink to the deep directory does not help: the home is canonicalized before the socket path is derived (visible above as /tmp resolving to /private/tmp), so the resolved long path still exceeds the limit.
Expected behavior
codex app-server daemon commands should work regardless of how deep CODEX_HOME is. Any of the following would solve it:
- An override for the control socket directory — a config key (e.g.
app_server.control_socket_dir), an environment variable, or a--sockflag on thedaemonsubcommands (matching the existingcodex app-server proxy --sock). - A short hashed default location when the derived path would exceed the platform limit — e.g.
$TMPDIR/codex-<hash-of-CODEX_HOME>/control.sock, similar to how OpenSSH solves the same problem withControlPath %C. - At minimum, a clearer error message that names
CODEX_HOMElength as the cause and suggests a workaround.
6 Comments
I checked current
mainand this still looks like a single choke point rather than a daemon-only bug.The default control socket path is built in
codex-rs/app-server-transport/src/transport/mod.rs:That same helper is used by:
codex-rs/app-server-daemon/src/lib.rsinDaemon::from_environment()for lifecycle commands such asversion,start,stop, etc.AppServerTransport::from_listen_url("unix://"), so the default Unix listener path has the same long-CODEX_HOMEexposure.codex app-server proxywhen--sockis omitted.So I would avoid fixing this only in the CLI command parser. A more robust fix would make
app_server_control_socket_path()return a platform-safe path by default, or add a single resolver beside it that all default-control-socket callers use.Patch shape that seems low-risk:
$CODEX_HOME/app-server-control/app-server-control.sockpath while it is short enough.CODEX_HOME, for example$TMPDIR/codex-app-server/<hash>/control.sock.CODEX_HOME; only the UDS rendezvous path needs to move.codex-rs/app-server-transport/src/transport/unix_socket_tests.rsfor a deepCODEX_HOMEand for stable hashing, plus one daemon/client smoke test if the final API surface changes.One small test detail:
find_codex_home()canonicalizesCODEX_HOME, so the regression test should create the deep directory first and assert against the canonical path length. That matches the reported/tmp->/private/tmpbehavior on macOS.I can reproduce the same failure on Ubuntu 24.04.4 LTS on WSL2.
Environment:
codex-cli 0.142.26.6.87.2-microsoft-standard-WSL22.6.3.0x86_64In my case this shows up when
CODEX_HOMEis configured under an XDG-style config path and resolves to a long path. The symlink/dotfiles detail is only one way to hit the issue; the underlying problem is that runtime socket paths are derived fromCODEX_HOME.I also think it would be useful to separate the default location question from the override question:
CODEX_HOMEby default.XDG_RUNTIME_DIRseems like a more appropriate default for runtime files.XDG_RUNTIME_DIRcan also be unsuitable in some environments, so a Codex-specific override such asCODEX_RUNTIME_DIRorCODEX_APP_SERVER_RUNTIME_DIRwould still be valuable.So the desired shape from my perspective would be:
CODEX_HOME.XDG_RUNTIME_DIRon Linux.I can reproduce this through Codex Desktop SSH to a Linux remote.
26.707.31428(build5059) on macOS 15.7.3codex-cli 0.144.1/rootis a symlink to a deeply nested persistent-volume pathSSH public-key authentication, the remote shell/version probes, and app-server bootstrap all succeed. The failure occurs when Desktop runs
codex app-server proxy:Desktop then surfaces only
ECONNRESET: socket hang up, making this look like an SSH/network failure.This confirms the same path-length bug also blocks the Desktop SSH flow. A short symlink does not help because
CODEX_HOMEis canonicalized; using a genuinely short real path/bind mount works around it.Still reproduces on current macOS builds (arm64), identically on both:
Including the
/tmp→/private/tmpcanonicalization that defeats short-symlink workarounds.Update — traced to a single choke point on current main:
app_server_control_socket_path()(codex-rs/app-server-transport/src/transport/mod.rs:54–62) always returnsCODEX_HOME/app-server-control/app-server-control.sock(+44 bytes), andfind_codex_home()canonicalizes aCODEX_HOMEenv value (codex-rs/utils/home-dir/src/lib.rs:45), hence/private/tmp.os/unix/net/addr.rs): macOSsun_pathis 104 bytes, so the usable budget for CODEX_HOME is 103 − 44 = 59 bytes.codex doctor,app-server proxy) funnels through that one function — which is also whydoctormisreports "stale or unreachable" here.The repo already solves this exact problem two other places:
codex-rs/linux-sandbox/src/proxy_routing.rs:58(UNIX_SOCKET_PATH_MAX_BYTES+/tmpfallback chain) andcodex-rs/tui/src/ide_context/ipc.rs:179–190($TMPDIR/codex-ipc/…fallback + explicitsockaddr_unlength checks). The control socket is the last unhandled site.Suggested fix (hybrid, zero migration): keep the classic path when it fits (≤103 bytes — every currently working install); otherwise fall back to a deterministic short path both daemon and clients can compute with no I/O:
(Linux: prefer
$XDG_RUNTIME_DIR/codex; root dir verified uid-owned + 0700.) Collision safety can be hardened for free by checkingInitializeResponse.codex_homeon fallback probes. Deep-CODEX_HOME installs are fully broken today, so there is nothing to stay compatible with.Still reproduces on 0.148.0 (release binary, macOS arm64), identically to 0.137–0.147:
Including the
/tmp→/private/tmpcanonicalization (+8 bytes) that defeats short-symlink workarounds.On current main the single choke point is unchanged:
app_server_control_socket_path()(codex-rs/app-server-transport/src/transport/mod.rs:58–64) still has no length handling, and every producer/consumer (daemon bind/connect, TUI auto-connect,codex doctor,app-server proxy) funnels through it. The hybrid fallback suggested in my earlier comment (keep the classic path when ≤103 bytes, otherwise a deterministic hashed short path both sides can compute without I/O) still applies; the in-tree templates for exactly this remaincodex-rs/linux-sandbox/src/proxy_routing.rsandcodex-rs/tui/src/ide_context/ipc.rs.I can confirm that this still reproduces on Codex CLI 0.149.1 when launched through Orca, which uses an isolated per-account
CODEX_HOME.### Environment
CODEX_HOMElength: 108 bytesThe generated path has this form:
```text
/Users/<user>/Library/Application Support/orca/codex-accounts/<account-id>/home/app-server-control/app-server-control.sock
Starting a normal Codex session through Orca produces:
Failed to start the background server: Error: app server did not become ready on <CODEX_HOME>/app-server-control/app-server-control.sock
Managed app-server stderr:
Error: path must be shorter than SUN_LEN
Caused by:
0: failed to connect to <CODEX_HOME>/app-server-control/app-server-control.sock
1: path must be shorter than SUN_LEN
The managed app-server binary is:
Codex CLI 0.149.1
codex doctor --json reports that the background server is not running, while the installation, configuration, authentication, and provider reachability checks all pass.
This is worth noting because the deep path is not an unusual project path configured manually. It is the default per-account home layout generated by Orca under macOS Application
Support. This means GUI or integration hosts that isolate Codex accounts can exceed the socket-path limit by default.
There is no existing control socket, and restarting only reproduces the same bind/connect failure. This confirms that the issue remains present in 0.149.1.