{"record":{"id":"1c1d2cfd3119b16e","repo":"juanfont/headscale","slug":"getting-user-w","errorCode":null,"errorMessage":"getting user: %w","messagePattern":"getting user: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"integration/helpers.go","lineNumber":1190,"sourceCode":"\t\tif len(updatedClients) != len(originalClients)+1 {\n\t\t\treturn struct{}{}, fmt.Errorf(\"expected %d clients, got %d\", len(originalClients)+1, len(updatedClients)) //nolint:err113\n\t\t}\n\n\t\tnewClient, err = FindNewClient(originalClients, updatedClients)\n\t\tif err != nil {\n\t\t\treturn struct{}{}, fmt.Errorf(\"finding new client: %w\", err)\n\t\t}\n\n\t\treturn struct{}{}, nil\n\t}, backoff.WithBackOff(backoff.NewConstantBackOff(500*time.Millisecond)), backoff.WithMaxElapsedTime(10*time.Second))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"timeout waiting for new client: %w\", err)\n\t}\n\n\t// Get the user and create preauth key\n\tuser, err := GetUserByName(headscale, username)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"getting user: %w\", err)\n\t}\n\n\tauthKey, err := s.CreatePreAuthKey(mustParseID(user.Id), true, false)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"creating preauth key: %w\", err)\n\t}\n\n\t// Login the new client\n\terr = newClient.Login(headscale.GetEndpoint(), authKey.Key)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"logging in new client: %w\", err)\n\t}\n\n\treturn newClient, nil\n}\n\n// MustAddAndLoginClient is like [Scenario.AddAndLoginClient] but fails the test on error.\nfunc (s *Scenario) MustAddAndLoginClient(","sourceCodeStart":1172,"sourceCodeEnd":1208,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/integration/helpers.go#L1172-L1208","documentation":"Raised in Scenario.AddAndLoginClient when GetUserByName(headscale, username) fails after the new client has been found. GetUserByName lists users via the headscale gRPC admin API inside the container and matches by name; failure means the API call errored or the user does not exist in the headscale database.","triggerScenarios":"AddAndLoginClient called with a username for which CreateUser was never run (or ran against a different headscale instance); the admin API exec inside the container fails; user was deleted between creation and this lookup.","commonSituations":"Test helper ordering bug — AddAndLoginClient invoked before Scenario.CreateUser; typo'd or case-mismatched username; headscale DB reset mid-test.","solutions":["Ensure Scenario.CreateUser(username, ...) succeeds before AddAndLoginClient","Verify the exact username string (case-sensitive match) is reused in both calls","List users in the container (`docker exec <hs> headscale users list`) to confirm the user exists","Check headscale container logs for gRPC/API errors during the lookup"],"exampleFix":"// before\nclient, err := scenario.AddAndLoginClient(t, \"user1\", tsVersion)\n// after\nerr := scenario.CreateUser(\"user1\")\nrequire.NoError(t, err)\nclient, err := scenario.AddAndLoginClient(t, \"user1\", tsVersion)","handlingStrategy":"validation","validationCode":"// Ensure the user exists before adding a client\nif _, err := scenario.GetUserByName? — use the helper directly:\nif _, err := integration.GetUserByName(headscale, username); err != nil {\n    t.Fatalf(\"user %q missing; call CreateUser first: %v\", username, err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pair AddAndLoginClient with a prior successful CreateUser for the same username","Reuse one constant for the username string in both calls","Never delete users mid-test while clients are being added"],"tags":["integration-test","user-management","grpc-api"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}