juanfont/headscale · error
user %s not found
Error message
user %s not found
What it means
Returned by the integration helper GetUserByName when ListUsers succeeded but no user with the requested name exists. It is a plain fmt.Errorf (marked nolint:err113) with the missing username.
Source
Thrown at integration/helpers.go:1086
EmailVerified: emailVerified,
}
}
// GetUserByName retrieves a user by name from the headscale server.
// This is a common pattern used when creating preauth keys or managing users.
func GetUserByName(headscale ControlServer, username string) (*clientv1.User, error) {
users, err := headscale.ListUsers()
if err != nil {
return nil, fmt.Errorf("listing users: %w", err)
}
for _, u := range users {
if u.Name == username {
return u, nil
}
}
return nil, fmt.Errorf("user %s not found", username) //nolint:err113
}
// findNode returns the first node in nodes for which match returns true,
// or nil if no node matches.
func findNode(nodes []*clientv1.Node, match func(*clientv1.Node) bool) *clientv1.Node {
for _, n := range nodes {
if match(n) {
return n
}
}
return nil
}
// mustParseID parses a string ID emitted by the HTTP client types into a
// uint64 for the APIs that still take numeric identifiers (NodeID, user and
// key IDs). It panics on malformed input, which only happens if the server
// emits a non-numeric ID — a bug worth failing the test loudly.View on GitHub (pinned to 565fd254d0)
Solutions
- Create the user (scenario.CreateUser / preauth flow) before calling GetUserByName
- Verify the exact name string, including case, matches the one used at creation
- Assert on list contents directly if absence is expected, instead of treating it as an error
Defensive patterns
Strategy: validation
Validate before calling
// create-if-missing pattern
users, _ := h.ListUsers()
exists := slices.ContainsFunc(users, func(u *clientv1.User) bool { return u.Name == username })
if !exists {
if _, err := scenario.CreateUser(username); err != nil {
return err
}
} Try / catch
u, err := GetUserByName(h, username)
if err != nil {
if strings.Contains(err.Error(), "not found") {
// create the user, then retry the lookup once
}
return err
} Prevention
- Derive usernames from one constant per scenario to avoid typos/case drift
- Order test steps: create users -> create nodes -> assert
When it happens
Trigger: Calling GetUserByName(t, headscale, "nonexistent") before that user was created, or after a cleanup removed it; also when the name has different case/whitespace than what was registered.
Common situations: Test ordering bugs — helper runs before the user-creation step; typos or case mismatches between the scenario users list and the lookup; parallel tests deleting shared users.
Related errors
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/90487472721e52b5.
Report an issue: GitHub.