juanfont/headscale · error
creating user: %w
Error message
creating user: %w
What it means
Returned by Scenario.CreatePreAuthKey when the headscale control server's gRPC/API call to mint a pre-auth key fails, despite the server handle being available. The message ("creating user") is misleading — the failing operation is headscale.CreateAuthKey for the given user ID.
Source
Thrown at integration/scenario.go:527
user := &User{
Clients: make(map[string]TailscaleClient),
}
s.users[userStr] = user
return user
}
// CreatePreAuthKey creates a "pre authentorised key" to be created in the
// Headscale instance on behalf of the [Scenario].
func (s *Scenario) CreatePreAuthKey(
user uint64,
reusable bool,
ephemeral bool,
) (*clientv1.PreAuthKey, error) {
if headscale, err := s.Headscale(); err == nil { //nolint:noinlineerr
key, err := headscale.CreateAuthKey(user, reusable, ephemeral)
if err != nil {
return nil, fmt.Errorf("creating user: %w", err)
}
return key, nil
}
return nil, fmt.Errorf("creating user: %w", errNoHeadscaleAvailable)
}
// CreatePreAuthKeyWithOptions creates a "pre authorised key" with the specified options
// to be created in the Headscale instance on behalf of the [Scenario].
func (s *Scenario) CreatePreAuthKeyWithOptions(opts hsic.AuthKeyOptions) (*clientv1.PreAuthKey, error) {
headscale, err := s.Headscale()
if err != nil {
return nil, fmt.Errorf("creating preauth key with options: %w", errNoHeadscaleAvailable)
}
key, err := headscale.CreateAuthKeyWithOptions(opts)
if err != nil {View on GitHub (pinned to 565fd254d0)
Solutions
- Create the user first: s.CreateUser("..."), then use the returned user ID for CreatePreAuthKey
- Print the wrapped error — a 'user not found' style message from the gRPC layer confirms the ID problem
- Verify the user still exists via headscale.ListUsers if earlier steps may have removed it
Example fix
// before
u, _ := scenario.CreateUser("alice")
key, err := scenario.CreatePreAuthKey(999, false, false)
// after
u, err := scenario.CreateUser("alice")
if err != nil {
t.Fatal(err)
}
key, err := scenario.CreatePreAuthKey(u.Id, false, false) Defensive patterns
Strategy: validation
Validate before calling
u, err := scenario.CreateUser(name)
if err != nil {
t.Fatal(err)
}
// only now is u.Id valid for key creation
_, err = scenario.CreatePreAuthKey(u.Id, reusable, ephemeral) Try / catch
key, err := scenario.CreatePreAuthKey(u.Id, reusable, ephemeral)
if err != nil {
t.Fatalf("preauth key creation failed (user %d exists?): %v", u.Id, err)
} Prevention
- Always create the user first and use the returned ID
- Never hardcode user IDs across scenario restarts
When it happens
Trigger: Calling s.CreatePreAuthKey(user, reusable, ephemeral) when the gRPC CreatePreAuthKey call inside the container returns an error, most commonly because the user ID does not exist in headscale.
Common situations: Test passes a user ID before calling s.CreateUser(user), or uses an ID from a different scenario/run; the user was deleted by an earlier test step; API key/machine auth to the local gRPC socket is broken.
Related errors
- creating preauth key with options: %w
- creating preauth key with tags: %w
- auth-key expired
- auth-key has already been used
- user mismatch
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/f96a3a7994170421.
Report an issue: GitHub.