juanfont/headscale · error

logging in new client: %w

Error message

logging in new client: %w

What it means

Final step error in Scenario.AddAndLoginClient: newClient.Login(headscale.GetEndpoint(), authKey.Key) failed. Login runs `tailscale up --login-server <endpoint> --authkey <key>` (plus options) inside the new tailscale container; failure means the node could not authenticate against headscale with the preauth key.

Source

Thrown at integration/helpers.go:1201

	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(
	t *testing.T,
	username string,
	version string,
	headscale ControlServer,
	tsOpts ...tsic.Option,
) TailscaleClient {
	t.Helper()

	client, err := s.AddAndLoginClient(t, username, version, headscale, tsOpts...)
	require.NoError(t, err)

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Read the tailscale container log for the `tailscale up` error (authkey rejected vs dial error vs TLS error)
  2. Confirm headscale.GetEndpoint() matches the server_url/TLS hostname configured for the container
  3. Verify the preauth key was created reusable and used only once per fresh node
  4. Check hs-*.stderr.log for registration endpoint errors
Defensive patterns

Strategy: retry

Validate before calling

// Sanity-check endpoint and key before login
if authKey.Key == "" { t.Fatal("empty authkey") }
ep := headscale.GetEndpoint()
if ep == "" { t.Fatal("empty headscale endpoint") }

Try / catch

if err := newClient.Login(headscale.GetEndpoint(), authKey.Key); err != nil {
    // dump tailscale container log for the real `tailscale up` failure
    newClient.MustLog(t) // or read container logs
    t.Fatalf("login failed: %v", err)
}

Prevention

When it happens

Trigger: Invalid/expired/reused preauth key; wrong endpoint (TLS hostname mismatch); tailscale client cannot reach the headscale port; authkey rejected because the node was already registered with different identity; version incompatibility between client and server noise protocol.

Common situations: Non-reusable key consumed by an earlier attempt; TLS cert hostname not matching the endpoint used; headscale server_url misconfigured in MinimumConfigYAML; old tailscale image lacking current noise handshake support.

Related errors


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