{"record":{"id":"714f8c27f3da527e","repo":"gravitational/teleport","slug":"user-logged-in-error","errorCode":null,"errorMessage":"User logged in error","messagePattern":"User logged in error","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"lib/srv/usermgmt.go","lineNumber":170,"sourceCode":"\ntype userCloser struct {\n\tusers    HostUsers\n\tbackend  HostUsersBackend\n\tusername string\n}\n\nfunc (u *userCloser) Close() error {\n\tteleportGroup, err := u.backend.LookupGroup(apiconstants.TeleportDropGroup)\n\tif err != nil {\n\t\treturn trace.Wrap(err)\n\t}\n\terr = u.users.doWithUserLock(func(sl types.SemaphoreLease) error {\n\t\treturn trace.Wrap(u.users.DeleteUser(u.username, teleportGroup.Gid))\n\t})\n\treturn trace.Wrap(err)\n}\n\nvar ErrUserLoggedIn = errors.New(\"User logged in error\")\n\ntype HostSudoers interface {\n\t// WriteSudoers creates a temporary Teleport user in the TeleportDropGroup\n\tWriteSudoers(name string, sudoers []string) error\n\t// RemoveSudoers removes the users sudoer file\n\tRemoveSudoers(name string) error\n}\n\ntype HostSudoersNotImplemented struct{}\n\n// WriteSudoers creates a temporary Teleport user in the TeleportDropGroup\nfunc (*HostSudoersNotImplemented) WriteSudoers(string, []string) error {\n\treturn trace.NotImplemented(\"host sudoers functionality not implemented on this platform\")\n}\n\n// RemoveSudoers removes the users sudoer file\nfunc (*HostSudoersNotImplemented) RemoveSudoers(name string) error {\n\treturn trace.NotImplemented(\"host sudoers functionality not implemented on this platform\")","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/gravitational/teleport/blob/1283425b60ec5f60d509ba4c791183d452923ff7/lib/srv/usermgmt.go#L152-L188","documentation":"ErrUserLoggedIn is a public sentinel error from host user management. It wraps the result of host.UserDel when the OS reports the exit code UserLoggedInExit, meaning the Unix user cannot be deleted because a login session is active. User management maps this to skip deletion gracefully (e.g. the temporary insecure-drop user with an active session is left in place and removed later).","triggerScenarios":"Calling DeleteUser (or the usermgmt backend delete path) with host.UserDel while the target Linux user has an active login session, yielding UserLoggedInExit which is converted to ErrUserLoggedIn.","commonSituations":"A user logs out but a lingering session (tmux, ssh connection, background process keeping the session) holds the account; TeleportDrop temporary user deletion while their SSH session is still open; insecure-drop cleanup racing an active session.","solutions":["No action needed: Teleport detects this and skips deletion, retrying on a later cleanup cycle","Ensure the user's sessions are terminated before manual user removal (log out, kill lingering processes)","Manually remove the user later with userdel once no sessions reference it"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"// check active sessions before deleting\nif sessionsActive(username) {\n    log.DebugContext(ctx, \"user has active session; deferring deletion\")\n    return nil\n}","typeGuard":"func isUserLoggedInErr(err error) bool { return errors.Is(err, ErrUserLoggedIn) }","tryCatchPattern":"err := u.backend.DeleteUser(username)\nif errors.Is(err, ErrUserLoggedIn) {\n    log.DebugContext(u.ctx, \"Skipping deletion of user with an active session\")\n    return nil\n}\nif err != nil { return trace.Wrap(err) }","preventionTips":["Treat ErrUserLoggedIn as retry-later, not fatal","Terminate user sessions before forced deletion","Rely on periodic cleanup to remove the user once sessions end"],"tags":["host-users","linux","session-conflict"],"backgroundTag":"user-deletion-blocked","analyzedSha":"1283425b60ec5f60d509ba4c791183d452923ff7","analyzedAt":"2026-09-02T04:06:41.601Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}