gravitational/teleport · warning
managed host users can not be converted to or from a static
Error message
managed host users can not be converted to or from a static host user
What it means
errStaticConversion is returned when ResolveGroups detects an attempt to convert a host user between auto-provisioned (managed) mode and static host user mode. Teleport forbids in-place conversion to prevent unexpected account state changes; the caller (UpsertUser) logs and aborts the update.
Source
Thrown at lib/srv/usermgmt.go:292
if errors.Is(err, host.ErrInvalidSudoers) {
u.log.WarnContext(context.Background(), "Invalid sudoers entry. If using a login managed by a static host user resource, inspect its configured sudoers field for invalid entries. Otherwise, inspect the host_sudoers field for roles targeting this host.", "error", err, "host_username", name)
return trace.BadParameter("invalid sudoers entry for login %q, inspect roles' host_sudoers field or static host user's sudoers field for invalid syntax", name)
}
return trace.Wrap(err)
}
func (u *HostSudoersManagement) RemoveSudoers(name string) error {
if err := u.backend.RemoveSudoersFile(name); err != nil {
return trace.Wrap(err)
}
return nil
}
// errUnmanagedUser is returned when attempting to modify or interact with a user that is not managed by Teleport.
var errUnmanagedUser = errors.New("user not managed by teleport")
// errStaticConversion is returned when attempting to convert a managed host user to or from a static host user
var errStaticConversion = errors.New("managed host users can not be converted to or from a static host user")
func (u *HostUserManagement) updateUser(hostUser HostUser, ui *decisionpb.HostUsersInfo) error {
ctx := u.ctx
log := u.log.With(
"host_username", hostUser.Name,
"mode", ui.GetMode(),
"uid", hostUser.UID,
"gid", hostUser.GID,
)
if ui.GetMode() == decisionpb.HostUserMode_HOST_USER_MODE_KEEP {
_, hasKeepGroup := hostUser.Groups[apiconstants.TeleportKeepGroup]
if !hasKeepGroup {
home, err := u.backend.GetDefaultHomeDirectory(hostUser.Name)
if err != nil {
return trace.Wrap(err)
}
View on GitHub (pinned to 1283425b60)
Solutions
- Remove the existing host user on the server and let Teleport recreate it in the desired mode
- Align the role's host user mode with the existing user's current mode instead of converting
- Plan migration explicitly: switch mode, then manually reconcile accounts on hosts
Example fix
// before: flipping mode for existing user host_users: mode: static // after: delete existing managed user on host first, then apply static mode, // or keep mode consistent with existing user state host_users: mode: keep # unchanged until accounts reconciled
Defensive patterns
Strategy: validation
Validate before calling
// ensure the user's current mode matches the target mode before upsert
currentlyStatic := isStaticHostUser(hostUser)
targetStatic := ui.GetMode() == decisionpb.HostUsersMode_HOST_USERS_MODE_STATIC
if currentlyStatic != targetStatic {
return trace.BadParameter("recreate user %s to change static/managed mode", hostUser.Name)
} Type guard
func isStaticConversionErr(err error) bool { return errors.Is(err, errStaticConversion) } Try / catch
if _, err := ResolveGroups(log, hostUser, ui, options.takeOwnership); err != nil {
if errors.Is(err, errStaticConversion) {
log.DebugContext(ctx, "cannot convert between auto-provisioned and static host users")
return nil
}
return trace.Wrap(err)
} Prevention
- Keep host user mode consistent per user across role updates
- Delete and recreate the account when switching modes
- Document mode changes as migration operations, not in-place edits
When it happens
Trigger: ResolveGroups (lib/srv/usermgmt.go:788) sees a user currently in static mode while the role/config declares it managed, or vice versa: (inStaticMode && managedUser) || (!inStaticMode && staticUser).
Common situations: Operator flips a role's host user mode (host_users mode static vs dynamic) for users that already exist on servers; migrating hosts between static host user definitions and auto-provisioning without cleanup.
Related errors
AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02).
Data as JSON: /api/errors/79a739f86b18c596.
Report an issue: GitHub.