netbirdio/netbird · error

failed to read profile config: %w

Error message

failed to read profile config: %w

What it means

profilemanager.ReadConfig could not read or parse the profile's JSON config. The file exists (os.Stat passed) but is unreadable (permissions, I/O error) or its content is not valid config JSON — typically a truncated or corrupted write from an earlier save.

Source

Thrown at client/android/profile_manager.go:192

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
	if _, err := os.Stat(configPath); os.IsNotExist(err) {
		return fmt.Errorf("profile '%s' does not exist", id)
	}

	// Read current config using internal profilemanager
	config, err := profilemanager.ReadConfig(configPath)
	if err != nil {
		return fmt.Errorf("failed to read profile config: %w", err)
	}

	// Clear authentication by removing private key and SSH key
	config.PrivateKey = ""
	config.SSHKey = ""

	// 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
}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Inspect the file content at configDir/profiles/<id>.json (or netbird.cfg for default)
  2. If corrupt, delete it — the next login recreates the config and the peer re-enrols
  3. Retry after the underlying storage issue is resolved
Defensive patterns

Strategy: try-catch

Validate before calling

// Optional pre-check that the config parses, before offering logout
if _, err := os.Stat(configPath); err == nil {
	if data, rerr := os.ReadFile(configPath); rerr == nil && !json.Valid(data) {
		// corrupt file: quarantine/delete it rather than calling LogoutProfile
	}
}

Try / catch

if err := pm.LogoutProfile(id); err != nil {
	if strings.Contains(err.Error(), "failed to read profile config") {
		// file exists but is unreadable/corrupt: inspect or delete it; next login recreates it
	}
}

Prevention

When it happens

Trigger: LogoutProfile hits a config file corrupted by an interrupted WriteOutConfig, a hand-edited file, or a read error from failing storage.

Common situations: App killed mid-write, disk-full during a previous save, files modified externally, aging flash storage producing read errors.

Related errors


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