netbirdio/netbird · error

failed to add profile: %w

Error message

failed to add profile: %w

What it means

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.

Source

Thrown at client/android/profile_manager.go:166

	// ServiceManager uses active_profile.json
	err := pm.serviceMgr.SetActiveProfileState(&profilemanager.ActiveProfileState{
		ID:       profilemanager.ID(id),
		Username: androidUsername,
	})
	if err != nil {
		return fmt.Errorf("failed to switch profile: %w", err)
	}

	log.Infof("switched to profile: %s", id)
	return nil
}

// AddProfile creates a new profile
func (pm *ProfileManager) AddProfile(profileName string) error {
	// Use ServiceManager (creates profile in profiles/ directory)
	profile, err := pm.serviceMgr.AddProfile(profileName, androidUsername)
	if err != nil {
		return fmt.Errorf("failed to add profile: %w", err)
	}

	log.Infof("created new profile: %s", profile.ID)
	return nil
}

// LogoutProfile logs out from a profile (clears authentication)
func (pm *ProfileManager) LogoutProfile(id string) error {
	configPath, err := pm.getProfileConfigPath(id)
	if err != nil {
		return err
	}

	if !profilemanager.IsValidProfileFilenameStem(profilemanager.ID(id)) {
		return fmt.Errorf("id '%s' is not valid", id)
	}

	// Check if profile exists

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Validate the name client-side before calling: non-empty after trim, at most 128 characters
  2. Retry with the trimmed name
  3. If the name is valid, check that profiles/ is creatable/writable and free space exists

Example fix

// before
pm.AddProfile(userInput) // "" or a 200-char string fails

// after
name := strings.TrimSpace(userInput)
if name == "" || utf8.RuneCountInString(name) > 128 {
	// reject in the UI before calling
}
pm.AddProfile(name)
Defensive patterns

Strategy: validation

Validate before calling

name := strings.TrimSpace(input)
if name == "" || utf8.RuneCountInString(name) > 128 {
	// reject in the UI before calling AddProfile
}

Type guard

func validProfileName(s string) bool {
	if !utf8.ValidString(s) {
		return false
	}
	s = strings.TrimSpace(s)
	return s != "" && utf8.RuneCountInString(s) <= 128
}

Try / catch

if err := pm.AddProfile(name); err != nil {
	if validProfileName(strings.TrimSpace(name)) {
		// name was fine → I/O problem: check profiles/ writability and free space
	} else {
		// validation problem: fix the input
	}
}

Prevention

When it happens

Trigger: 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.

Common situations: UI passing an empty string when the user confirms the dialog too early, a pasted 129+ character name, storage full at creation time.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/00308aa3b6d702fa. Report an issue: GitHub.