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

  1. Read the wrapped error — it names the client and the command that failed.
  2. Wait for the client to be ready (login done, tailscaled up) before querying IPs — use an Eventually-style retry in tests.
  3. 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

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


AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15). Data as JSON: /api/errors/72c46a9db8791e8d. Report an issue: GitHub.