netbirdio/netbird · error
failed to rename profile: %w
Error message
failed to rename profile: %w
What it means
RenameProfile delegates to ServiceManager.RenameProfile, which validates both the id (filename-stem rules) and the new display name (non-empty after sanitization, valid UTF-8, at most 128 runes), then rewrites only the "name" field of the profile config — the id and on-disk filename stay fixed. The error wraps a validation failure or the config read/write I/O.
Source
Thrown at client/android/profile_manager.go:217
// Save config using internal profilemanager
if err := profilemanager.WriteOutConfig(configPath, config); err != nil {
return fmt.Errorf("failed to save config: %w", err)
}
// The stored account email is kept on purpose, matching the desktop and CLI
// logout semantics: the next login passes it as the login_hint so the IdP
// preselects the account. Removing the profile is what deletes it.
log.Infof("logged out from profile: %s", id)
return nil
}
// RenameProfile changes a profile's display name. The profile ID, and therefore
// its on-disk filename, is left untouched: only the "name" field of the config
// is rewritten. This works for the default profile too, whose config lives in
// netbird.cfg rather than under profiles/.
func (pm *ProfileManager) RenameProfile(id string, newName string) error {
if err := pm.serviceMgr.RenameProfile(profilemanager.ID(id), androidUsername, newName); err != nil {
return fmt.Errorf("failed to rename profile: %w", err)
}
log.Infof("renamed profile %s to: %s", id, newName)
return nil
}
// RemoveProfile deletes a profile
func (pm *ProfileManager) RemoveProfile(id string) error {
configPath, err := pm.getProfileConfigPath(id)
if err != nil {
return err
}
// Use ServiceManager (removes profile from profiles/ directory)
if err := pm.serviceMgr.RemoveProfile(profilemanager.ID(id), androidUsername); err != nil {
return fmt.Errorf("failed to remove profile: %w", err)
}
View on GitHub (pinned to 93e97f4bf1)
Solutions
- Use the id from ListProfiles, never the display name
- Trim the new name and cap it at 128 characters
- If both are valid, check storage health and retry
Example fix
// before pm.RenameProfile(profile.Name, newName) // after pm.RenameProfile(profile.ID, strings.TrimSpace(newName))
Defensive patterns
Strategy: validation
Validate before calling
newName = strings.TrimSpace(newName)
if newName == "" || utf8.RuneCountInString(newName) > 128 || !isValidProfileID(id) {
// reject in the UI before calling RenameProfile
} Type guard
func validRename(id, name string) bool {
return isValidProfileID(id) && utf8.RuneCountInString(strings.TrimSpace(name)) <= 128 && strings.TrimSpace(name) != ""
} Try / catch
if err := pm.RenameProfile(id, newName); err != nil {
if !validRename(id, newName) {
// input problem: fix id (use ListProfiles value) or name
} else {
// I/O problem: check storage and retry
}
} Prevention
- Always rename by id from ListProfiles, never by display name
- Trim and cap new names in the UI
- Remember the id and filename never change — only the stored name field
When it happens
Trigger: RenameProfile with a display name or path-like string as the id, a new name that is empty after trimming or longer than 128 characters, or a profile config file that is missing/unwritable at save time.
Common situations: UI sending the Name field as the id, a blank new name from an empty dialog, storage issues at the moment of the rewrite.
Related errors
- failed to add profile: %w
- id '%s' is not valid
- id %q is not valid
- failed to list profiles: %w
- failed to get active profile: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/8615cb3637ea9295.
Report an issue: GitHub.