juanfont/headscale · error
getting IPs: %w
Error message
getting IPs: %w
What it means
Inside `Scenario.GetIPs(user)`, one of the user's tailscale clients failed to report its IP addresses (`client.IPs()` returned an error). The partial `ips` slice is returned alongside the error. Typically the underlying failure is a `tailscale status`/`ip` command failing inside the client container.
Source
Thrown at integration/scenario.go:1408
---
%s - method: %s | url: %s
%s - status: %d | cookies: %+v
---
`, t.Hostname, req.Method, req.URL.String(), t.Hostname, resp.StatusCode, resp.Cookies())
return resp, nil
}
// GetIPs returns all [netip.Addr] of [TailscaleClient]s associated with a [User]
// in a [Scenario].
func (s *Scenario) GetIPs(user string) ([]netip.Addr, error) {
var ips []netip.Addr
if ns, ok := s.users[user]; ok {
for _, client := range ns.Clients {
clientIps, err := client.IPs()
if err != nil {
return ips, fmt.Errorf("getting IPs: %w", err)
}
ips = append(ips, clientIps...)
}
return ips, nil
}
return ips, fmt.Errorf("getting IPs: %w", errNoUserAvailable)
}
// GetClients returns all [TailscaleClient]s associated with a [User] in a [Scenario].
func (s *Scenario) GetClients(user string) ([]TailscaleClient, error) {
if ns, ok := s.users[user]; ok {
return xmaps.Values(ns.Clients), nil
}
return nil, fmt.Errorf("getting clients: %w", errNoUserAvailable)View on GitHub (pinned to 565fd254d0)
Solutions
- Read the wrapped error — it names the client and the command that failed.
- Wait for the client to be ready (login done, tailscaled up) before querying IPs — use an Eventually-style retry in tests.
- Check `docker ps` / container logs for the failing client.
Example fix
// before
ips, err := scenario.GetIPs(user) // direct call, fails while tailscaled boots
// after
require.Eventually(t, func() bool {
_, err := scenario.GetIPs(user)
return err == nil
}, 30*time.Second, 500*time.Millisecond) Defensive patterns
Strategy: retry
Try / catch
// Tolerate startup lag with bounded retries.
var ips []netip.Addr
err := retry(10, 2*time.Second, func() error {
var e error
ips, e = s.GetIPs(user)
return e
}) Prevention
- Wait for client login/state before querying IPs (EventuallyWithT).
- Check container liveness when a single client repeatedly fails.
- Remember GetIPs returns partial data with the error — do not use ips on err != nil.
When it happens
Trigger: Iterating `ns.Clients` and calling `client.IPs()` while a container is still starting, has crashed, or its tailscaled is not yet running — the wrapped error describes the exact command failure.
Common situations: Calling GetIPs immediately after client creation without waiting for tailscaled readiness; container exited during the test; retries needed because IP assignment lags login.
Related errors
- %s failed to fetch tailscale status: %w
- reaching DERP server: %w
- no network set, called from: %s
- running pre-built tailscale container %q: %w
- %s could not start tailscale container (version: %s): %w Do
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/72c46a9db8791e8d.
Report an issue: GitHub.