{"record":{"id":"8615cb3637ea9295","repo":"netbirdio/netbird","slug":"failed-to-rename-profile-w","errorCode":null,"errorMessage":"failed to rename profile: %w","messagePattern":"failed to rename profile: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/android/profile_manager.go","lineNumber":217,"sourceCode":"\t// Save config using internal profilemanager\n\tif err := profilemanager.WriteOutConfig(configPath, config); err != nil {\n\t\treturn fmt.Errorf(\"failed to save config: %w\", err)\n\t}\n\n\t// The stored account email is kept on purpose, matching the desktop and CLI\n\t// logout semantics: the next login passes it as the login_hint so the IdP\n\t// preselects the account. Removing the profile is what deletes it.\n\tlog.Infof(\"logged out from profile: %s\", id)\n\treturn nil\n}\n\n// RenameProfile changes a profile's display name. The profile ID, and therefore\n// its on-disk filename, is left untouched: only the \"name\" field of the config\n// is rewritten. This works for the default profile too, whose config lives in\n// netbird.cfg rather than under profiles/.\nfunc (pm *ProfileManager) RenameProfile(id string, newName string) error {\n\tif err := pm.serviceMgr.RenameProfile(profilemanager.ID(id), androidUsername, newName); err != nil {\n\t\treturn fmt.Errorf(\"failed to rename profile: %w\", err)\n\t}\n\n\tlog.Infof(\"renamed profile %s to: %s\", id, newName)\n\treturn nil\n}\n\n// RemoveProfile deletes a profile\nfunc (pm *ProfileManager) RemoveProfile(id string) error {\n\tconfigPath, err := pm.getProfileConfigPath(id)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Use ServiceManager (removes profile from profiles/ directory)\n\tif err := pm.serviceMgr.RemoveProfile(profilemanager.ID(id), androidUsername); err != nil {\n\t\treturn fmt.Errorf(\"failed to remove profile: %w\", err)\n\t}\n","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/android/profile_manager.go#L199-L235","documentation":"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.","triggerScenarios":"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.","commonSituations":"UI sending the Name field as the id, a blank new name from an empty dialog, storage issues at the moment of the rewrite.","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"],"exampleFix":"// before\npm.RenameProfile(profile.Name, newName)\n\n// after\npm.RenameProfile(profile.ID, strings.TrimSpace(newName))","handlingStrategy":"validation","validationCode":"newName = strings.TrimSpace(newName)\nif newName == \"\" || utf8.RuneCountInString(newName) > 128 || !isValidProfileID(id) {\n\t// reject in the UI before calling RenameProfile\n}","typeGuard":"func validRename(id, name string) bool {\n\treturn isValidProfileID(id) && utf8.RuneCountInString(strings.TrimSpace(name)) <= 128 && strings.TrimSpace(name) != \"\"\n}","tryCatchPattern":"if err := pm.RenameProfile(id, newName); err != nil {\n\tif !validRename(id, newName) {\n\t\t// input problem: fix id (use ListProfiles value) or name\n\t} else {\n\t\t// I/O problem: check storage and retry\n\t}\n}","preventionTips":["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"],"tags":["android","go","profile","validation","rename"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}