juanfont/headscale · error

getting user: %w

Error message

getting user: %w

What it means

Raised in Scenario.AddAndLoginClient when GetUserByName(headscale, username) fails after the new client has been found. GetUserByName lists users via the headscale gRPC admin API inside the container and matches by name; failure means the API call errored or the user does not exist in the headscale database.

Source

Thrown at integration/helpers.go:1190

		if len(updatedClients) != len(originalClients)+1 {
			return struct{}{}, fmt.Errorf("expected %d clients, got %d", len(originalClients)+1, len(updatedClients)) //nolint:err113
		}

		newClient, err = FindNewClient(originalClients, updatedClients)
		if err != nil {
			return struct{}{}, fmt.Errorf("finding new client: %w", err)
		}

		return struct{}{}, nil
	}, backoff.WithBackOff(backoff.NewConstantBackOff(500*time.Millisecond)), backoff.WithMaxElapsedTime(10*time.Second))
	if err != nil {
		return nil, fmt.Errorf("timeout waiting for new client: %w", err)
	}

	// Get the user and create preauth key
	user, err := GetUserByName(headscale, username)
	if err != nil {
		return nil, fmt.Errorf("getting user: %w", err)
	}

	authKey, err := s.CreatePreAuthKey(mustParseID(user.Id), true, false)
	if err != nil {
		return nil, fmt.Errorf("creating preauth key: %w", err)
	}

	// Login the new client
	err = newClient.Login(headscale.GetEndpoint(), authKey.Key)
	if err != nil {
		return nil, fmt.Errorf("logging in new client: %w", err)
	}

	return newClient, nil
}

// MustAddAndLoginClient is like [Scenario.AddAndLoginClient] but fails the test on error.
func (s *Scenario) MustAddAndLoginClient(

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Ensure Scenario.CreateUser(username, ...) succeeds before AddAndLoginClient
  2. Verify the exact username string (case-sensitive match) is reused in both calls
  3. List users in the container (`docker exec <hs> headscale users list`) to confirm the user exists
  4. Check headscale container logs for gRPC/API errors during the lookup

Example fix

// before
client, err := scenario.AddAndLoginClient(t, "user1", tsVersion)
// after
err := scenario.CreateUser("user1")
require.NoError(t, err)
client, err := scenario.AddAndLoginClient(t, "user1", tsVersion)
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the user exists before adding a client
if _, err := scenario.GetUserByName? — use the helper directly:
if _, err := integration.GetUserByName(headscale, username); err != nil {
    t.Fatalf("user %q missing; call CreateUser first: %v", username, err)
}

Prevention

When it happens

Trigger: AddAndLoginClient called with a username for which CreateUser was never run (or ran against a different headscale instance); the admin API exec inside the container fails; user was deleted between creation and this lookup.

Common situations: Test helper ordering bug — AddAndLoginClient invoked before Scenario.CreateUser; typo'd or case-mismatched username; headscale DB reset mid-test.

Related errors


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