fix(docker): disable IPv6 on the gateway network #515

Merged
didericis merged 1 commits from fix-gateway-disable-ipv6 into main 2026-07-26 18:33:53 -04:00
Collaborator

Summary

The docker integration suite fails intermittently with a docker-internal parse error, e.g. in run 3500 / job 6658:

ConsolidatedLaunchError: gateway network bot-bottle-gateway has no subnet:
  ParseAddr("fdd0:0:0:6::1/64"): unexpected character, want colon (at "/64")

The ParseAddr(...) text is docker's own Go stderrdocker network inspect itself is failing (the same run also shows docker network ls exiting non-zero), so it is a daemon-state problem, not a code regression.

Root cause

  1. The CI runner's docker daemon default-enables IPv6 (default-address-pools with an fdd0::/48 ULA range).
  2. _ensure_network creates the gateway net with only --subnet (gateway.py), so the daemon also attaches an IPv6 subnet whose gateway is stored as fdd0:0:0:N::1/64.
  3. A moby bug makes docker network inspect/ls choke calling netip.ParseAddr on that ::1/64 value, poisoning every command that reads the network — so _network_cidr can't read the subnet and the launch aborts.

It looks flaky because the N is the daemon's IPv6 pool index (runner-state-dependent): integration-docker failed on #507 and #511 but passed on #513, #508, and main with identical code.

Fix

bot-bottle attribution pins IPv4 source IPs and has no IPv6 support, so pass --ipv6=false explicitly at docker network create. That keeps the gateway network IPv4-only regardless of the daemon default, so the malformed IPv6 gateway can never be attached.

Note for the runner

An already-poisoned runner still needs a one-time docker network rm bot-bottle-gateway (and possibly a docker daemon restart, since network ls/inspect are poisoned) to clear the existing malformed network. This PR prevents recurrence.

Tests

Updated test_ensure_running_creates_network_when_missing to assert --ipv6=false is in the create argv. Full test_orchestrator_gateway suite passes (29 tests).

🤖 Generated with Claude Code

## Summary The docker integration suite fails intermittently with a docker-internal parse error, e.g. in [run 3500 / job 6658](https://gitea.dideric.is/didericis/bot-bottle/actions/runs/3500/jobs/6658): ``` ConsolidatedLaunchError: gateway network bot-bottle-gateway has no subnet: ParseAddr("fdd0:0:0:6::1/64"): unexpected character, want colon (at "/64") ``` The `ParseAddr(...)` text is **docker's own Go stderr** — `docker network inspect` itself is failing (the same run also shows `docker network ls` exiting non-zero), so it is a daemon-state problem, not a code regression. ## Root cause 1. The CI runner's docker daemon default-enables IPv6 (`default-address-pools` with an `fdd0::/48` ULA range). 2. `_ensure_network` creates the gateway net with only `--subnet` (`gateway.py`), so the daemon *also* attaches an IPv6 subnet whose gateway is stored as `fdd0:0:0:N::1/64`. 3. A moby bug makes `docker network inspect`/`ls` choke calling `netip.ParseAddr` on that `::1/64` value, poisoning every command that reads the network — so `_network_cidr` can't read the subnet and the launch aborts. It looks flaky because the `N` is the daemon's IPv6 pool index (runner-state-dependent): integration-docker failed on #507 and #511 but passed on #513, #508, and main with identical code. ## Fix bot-bottle attribution pins IPv4 source IPs and has no IPv6 support, so pass `--ipv6=false` explicitly at `docker network create`. That keeps the gateway network IPv4-only regardless of the daemon default, so the malformed IPv6 gateway can never be attached. ## Note for the runner An **already-poisoned** runner still needs a one-time `docker network rm bot-bottle-gateway` (and possibly a docker daemon restart, since `network ls`/`inspect` are poisoned) to clear the existing malformed network. This PR prevents recurrence. ## Tests Updated `test_ensure_running_creates_network_when_missing` to assert `--ipv6=false` is in the create argv. Full `test_orchestrator_gateway` suite passes (29 tests). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
didericis-claude added 1 commit 2026-07-26 18:31:28 -04:00
fix(docker): disable IPv6 on the gateway network
prd-number-check / require-numbered-prds (pull_request) Successful in 7s
lint / lint (push) Successful in 1m1s
test / unit (pull_request) Successful in 46s
test / integration-docker (pull_request) Successful in 1m5s
test / coverage (pull_request) Successful in 20s
tracker-policy-pr / check-pr (pull_request) Successful in 7s
592949d6cd
On a docker daemon that default-enables IPv6 (default-address-pools),
creating the gateway network with only `--subnet` lets the daemon also
attach an fdd0::/64 IPv6 subnet. Its gateway is stored as `::1/64`,
which trips docker's own netip.ParseAddr in `network inspect`/`ls`:

  ParseAddr("fdd0:0:0:6::1/64"): unexpected character, want colon

That poisons every `_network_cidr`/`network ls` read and fails the
docker integration suite intermittently (whichever run the runner's
IPv6 pool index lands on a broken network). bot-bottle attribution
pins IPv4 source IPs and has no IPv6 support, so pass `--ipv6=false`
explicitly at network create to keep the gateway network IPv4-only
regardless of the daemon default.

Note: an already-poisoned runner still needs a one-time
`docker network rm bot-bottle-gateway` (and possibly a daemon
restart) to clear the malformed network.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
didericis added the Kind/Bug label 2026-07-26 18:32:59 -04:00
didericis merged commit 85fb6b0c98 into main 2026-07-26 18:33:53 -04:00
didericis deleted branch fix-gateway-disable-ipv6 2026-07-26 18:33:59 -04:00
Sign in to join this conversation.