juanfont/headscale · error
finding user: %w
Error message
finding user: %w
What it means
During the auth callback (OIDC/interactive login), looking up the user selected for the new registration failed: s.db.GetUserByID(userID) errored. The registration cache entry was already fetched successfully, so this is purely a user-table read failure or a missing user record.
Source
Thrown at hscontrol/state/state.go:2220
}
// HandleNodeFromAuthPath handles node registration through authentication flow (like OIDC).
func (s *State) HandleNodeFromAuthPath(
authID types.AuthID,
userID types.UserID,
expiry *time.Time,
registrationMethod string,
) (types.NodeView, change.Change, error) {
// Get the registration entry from cache
regEntry, ok := s.GetAuthCacheEntry(authID)
if !ok {
return types.NodeView{}, change.Change{}, hsdb.ErrNodeNotFoundRegistrationCache
}
// Get the user
user, err := s.db.GetUserByID(userID)
if err != nil {
return types.NodeView{}, change.Change{}, fmt.Errorf("finding user: %w", err)
}
regData := regEntry.RegistrationData()
// Hostname was already validated/normalised at producer time. Build
// the initial Hostinfo from the cached client-supplied Hostinfo (or
// an empty stub if the client did not send one).
hostname := regData.Hostname
hostinfo := &tailcfg.Hostinfo{}
if regData.Hostinfo != nil {
hostinfo = regData.Hostinfo.Clone()
}
hostinfo.Hostname = hostname
// Lookup existing nodes
machineKey := regData.MachineKeyView on GitHub (pinned to 565fd254d0)
Solutions
- Confirm the user still exists: `headscale users list`
- If deleted, restart the login flow for a valid user
- For DB read errors, restore connectivity and retry — the client re-initiates registration cleanly
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the user exists before completing the callback:
if _, err := db.GetUserByID(userID); err != nil {
http.Redirect(w, r, "/register?error=user_missing", http.StatusTemporaryRedirect)
return
} Try / catch
node, ch, err := s.CompleteRegistration(authID, userID, ...)
if err != nil && strings.Contains(err.Error(), "finding user") {
// user deleted mid-login; restart flow with a fresh auth URL
s.authCache.Remove(authID)
renderError(w, "user no longer exists; start a new login")
return
} Prevention
- Do not delete users with in-flight logins; expire their sessions first
- Keep auth-cache TTLs short so stale callbacks fail fast
- Distinguish this from hsdb.ErrNodeNotFoundRegistrationCache (missing reg entry) in handling
When it happens
Trigger: CompleteRegisterWithAuthKey/auth callback invoked with a userID that does not exist (user deleted between login start and callback), or the DB read fails outright — connection dropped, table locked, Postgres failover.
Common situations: Admin deletes a user while that user's OIDC login is in flight; long-lived browser login page resumed after the user was removed; transient DB outage at callback time.
Related errors
- updating policy manager users: %w
- registering existing node in database: %w
- saving node to database: %w
- using pre auth key: %w
- node not found
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/95806afcbc3005a5.
Report an issue: GitHub.