juanfont/headscale · error

creating preauth key: %w

Error message

creating preauth key: %w

What it means

Thrown when Scenario.CreatePreAuthKey(userID, reusable=true, ephemeral=false) fails while adding and logging in a client. This call exercises the headscale preauthkey gRPC endpoint; failure means the API rejected the create request (validation, database error) or the container exec/API transport failed.

Source

Thrown at integration/helpers.go:1195

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

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Check hs-*.stderr.log for the gRPC error returned by the preauthkey service
  2. Confirm the user from GetUserByName still exists and its Id parses via mustParseID
  3. If using Postgres, verify the postgres container is healthy (see error 668)
  4. Re-run to rule out a transient DB lock on SQLite
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify user exists right before key creation
user, err := integration.GetUserByName(headscale, username)
if err != nil { t.Fatal(err) }
// mustParseID(user.Id) must succeed; guard it:
if user.Id == "" { t.Fatal("empty user id") }

Try / catch

authKey, err := s.CreatePreAuthKey(mustParseID(user.Id), true, false)
if err != nil {
    t.Fatalf("preauth key creation failed; check DB backend health: %v", err)
}

Prevention

When it happens

Trigger: The preauthkey.Create RPC returns an error: invalid user ID from mustParseID, DB constraint failure, or expired/malformed auth for the admin API; alternatively the exec into the headscale container failed. Called with reusable=true and ephemeral=false in this path.

Common situations: Database backend issues (Postgres container not ready, SQLite locked); user record deleted between GetUserByName and this call; headscale binary in container crashing on the RPC.

Related errors


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