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
- Check hs-*.stderr.log for the gRPC error returned by the preauthkey service
- Confirm the user from GetUserByName still exists and its Id parses via mustParseID
- If using Postgres, verify the postgres container is healthy (see error 668)
- 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
- On Postgres runs, wait for the postgres container before creating keys
- Check hs-*.stderr.log for the underlying gRPC status when this fires
- Create keys only for users you just verified exist
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
- getting user: %w
- creating user: %w
- creating preauth key with options: %w
- creating preauth key with tags: %w
- auth-key expired
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/e42f6e9f79011fe7.
Report an issue: GitHub.