Repository navigation
2.87.0 startup crash-loops on hosts with IPv6 disabled on loopback (::1 timeout treated as unclassifiable owner evidence) #7258
Description
Client or integration
Other
Area
Service lifecycle
Summary
On hosts where IPv6 is disabled on the loopback interface (net.ipv6.conf.lo.disable_ipv6=1, with all/default also disabled), 2.87.0 refuses to start and crash-loops under systemd.
The new cross-home owner discovery probes both loopback families of every candidate port. On such a host, ::1 is no longer a local address: packets are routed out eth0 toward the IPv6 gateway and dropped, so TCP connects to [::1]:<port> time out instead of being refused. classifyHealthz maps a timeout to "unknown", findCrossHomeOwnerDetailed turns that into an indeterminate verdict, and markCrossHomeSibling refuses startup — even though the IPv4 probe of the same port returned a clean connection refusal ("dead").
Observed on a hub-role deployment whose ~/.codex/config.toml / ~/.grok managed region reference the hub's client-routing port (10102). Note the ordering aspect: the hub binds that port only after the cross-home check, so hub deployments cannot rely on bind order to avoid probing it.
Expected: a loopback family that times out, when the other family of the same port cleanly refuses, should not be fatal owner evidence (or this indeterminate case should warn rather than block startup). Hosts that deliberately disable IPv6 (a common hardening preset, e.g. /etc/sysctl.d/99-disable-ipv6.conf) become permanently unable to start the service after upgrading to 2.87.0.
Reproduction
- On Ubuntu, set
/etc/sysctl.d/99-disable-ipv6.conf:net.ipv6.conf.all.disable_ipv6=1,net.ipv6.conf.default.disable_ipv6=1,net.ipv6.conf.lo.disable_ipv6=1; reboot orsysctl --system. - Verify the quirk:
python3 -c "import socket; s=socket.socket(socket.AF_INET6); s.settimeout(2); s.connect(('::1', 10102))"→TimeoutError(on a healthy host this is an instantConnectionRefusedError). - Have any cross-home candidate port referenced from client state (e.g.
~/.codex/config.tomlwithopenai_base_url = http://127.0.0.1:10102/v1, or a grok managed block). npm i -g @bitkyc08/opencodex@2.87.0and restart the service → immediate exit with the error below; systemd restarts every ~6 s forever.
Fix on our side (service starts immediately): sysctl -w net.ipv6.conf.lo.disable_ipv6=0 and persist. ip -6 route get ::1 changes from via fe80::1 dev eth0 to local ::1 dev lo.
Version
2.87.0
Operating system
Ubuntu (Contabo VPS, x64); the quirk is generic to Linux hosts with IPv6 disabled on lo
Provider and model
n/a — startup path, no provider traffic
Logs or error output
error: Shared-client owner could not be verified (a managed client port answered but its listener could not be classified); refusing startup before any shared-client write. Retry startup after discovery recovers.
at markCrossHomeSibling (/…/src/cli/cross-home-owner.ts:303:15)
Probe evidence on the affected host:
$ python3 - <<'PY'
import socket
for host, port in (("127.0.0.1", 10102), ("::1", 10102)):
s = socket.socket(socket.AF_INET6 if ":" in host else socket.AF_INET, socket.SOCK_STREAM); s.settimeout(2)
try: s.connect((host, port)); print(host, "CONNECTED")
except Exception as e: print(host, type(e).__name__)
s.close()
PY
127.0.0.1 ConnectionRefusedError
::1 TimeoutError
$ sysctl net.ipv6.conf.lo.disable_ipv6
net.ipv6.conf.lo.disable_ipv6 = 1
$ ip -6 route get ::1 # before fix
::1 from :: via fe80::1 dev eth0 proto static src fe80::… metric 1024
Screenshots and supporting files
n/a
Redacted configuration
n/a — standard hub deployment; client homes reference the hub loopback port (10102)
Checks
- I searched existing issues and documentation.
- I removed secrets, tokens, account details, request credentials, and personal data.
Activity
lidge-jun commentedon Oct 17, 2026
Fixed on dev by #7262 (43a3e39): startup now checks whether each loopback address can be bound and skips a family that is unavailable (EADDRNOTAVAIL/EAFNOSUPPORT), so an IPv6-disabled loopback no longer crash-loops. Timeouts on an available family still refuse startup. Ships in 2.88.0.