{"record":{"id":"00308aa3b6d702fa","repo":"netbirdio/netbird","slug":"failed-to-add-profile-w","errorCode":null,"errorMessage":"failed to add profile: %w","messagePattern":"failed to add profile: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/android/profile_manager.go","lineNumber":166,"sourceCode":"\t// ServiceManager uses active_profile.json\n\terr := pm.serviceMgr.SetActiveProfileState(&profilemanager.ActiveProfileState{\n\t\tID:       profilemanager.ID(id),\n\t\tUsername: androidUsername,\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to switch profile: %w\", err)\n\t}\n\n\tlog.Infof(\"switched to profile: %s\", id)\n\treturn nil\n}\n\n// AddProfile creates a new profile\nfunc (pm *ProfileManager) AddProfile(profileName string) error {\n\t// Use ServiceManager (creates profile in profiles/ directory)\n\tprofile, err := pm.serviceMgr.AddProfile(profileName, androidUsername)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to add profile: %w\", err)\n\t}\n\n\tlog.Infof(\"created new profile: %s\", profile.ID)\n\treturn nil\n}\n\n// LogoutProfile logs out from a profile (clears authentication)\nfunc (pm *ProfileManager) LogoutProfile(id string) error {\n\tconfigPath, err := pm.getProfileConfigPath(id)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif !profilemanager.IsValidProfileFilenameStem(profilemanager.ID(id)) {\n\t\treturn fmt.Errorf(\"id '%s' is not valid\", id)\n\t}\n\n\t// Check if profile exists","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/android/profile_manager.go#L148-L184","documentation":"AddProfile sanitizes the display name (rejects empty-after-trim, invalid UTF-8, and names over 128 runes), generates a fresh hex ID, and writes the new profile config into profiles/. The error wraps either that name validation failure or the I/O failure of creating the file/directory.","triggerScenarios":"AddProfile(profileName) with a name that is empty, only whitespace/control characters after stripping, not valid UTF-8, or longer than 128 characters; or a profiles/ directory that cannot be created or written.","commonSituations":"UI passing an empty string when the user confirms the dialog too early, a pasted 129+ character name, storage full at creation time.","solutions":["Validate the name client-side before calling: non-empty after trim, at most 128 characters","Retry with the trimmed name","If the name is valid, check that profiles/ is creatable/writable and free space exists"],"exampleFix":"// before\npm.AddProfile(userInput) // \"\" or a 200-char string fails\n\n// after\nname := strings.TrimSpace(userInput)\nif name == \"\" || utf8.RuneCountInString(name) > 128 {\n\t// reject in the UI before calling\n}\npm.AddProfile(name)","handlingStrategy":"validation","validationCode":"name := strings.TrimSpace(input)\nif name == \"\" || utf8.RuneCountInString(name) > 128 {\n\t// reject in the UI before calling AddProfile\n}","typeGuard":"func validProfileName(s string) bool {\n\tif !utf8.ValidString(s) {\n\t\treturn false\n\t}\n\ts = strings.TrimSpace(s)\n\treturn s != \"\" && utf8.RuneCountInString(s) <= 128\n}","tryCatchPattern":"if err := pm.AddProfile(name); err != nil {\n\tif validProfileName(strings.TrimSpace(name)) {\n\t\t// name was fine → I/O problem: check profiles/ writability and free space\n\t} else {\n\t\t// validation problem: fix the input\n\t}\n}","preventionTips":["Trim and cap names at 128 characters in the UI","Disable the confirm button while the name field is empty","Reject pasted control-character-only input before it reaches the API"],"tags":["android","go","profile","validation"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}