netbirdio/netbird · error

add profile failed: %w

Error message

add profile failed: %w

What it means

addProfileOnDaemon (client/cmd/profile.go:332-343) is the shared entry point for profile creation used by `netbird profile add` and the `netbird up --profile <name>` auto-create path. The error wraps any AddProfile RPC failure: daemon-side validation of the profile name, storage errors, or gRPC-level failures (Unavailable while the daemon restarts). The %w wrap preserves the daemon's status message in the chain.

Source

Thrown at client/cmd/profile.go:340

			return errors.New(msg + "\nRun `netbird profile list --show-id` to see IDs, then select by ID prefix:\n  netbird profile select|remove <id-prefix>")
		}
	case codes.NotFound:
		return fmt.Errorf("profile %q not found", handle)
	}
	return err
}

// addProfileOnDaemon issues the AddProfile RPC on an existing daemon client
// and returns the new profile's ID. It is the single entry point for profile
// creation, shared by `netbird profile add` and the `netbird up --profile
// <name>` auto-create path.
func addProfileOnDaemon(ctx context.Context, client proto.DaemonServiceClient, profileName, username string) (profilemanager.ID, error) {
	resp, err := client.AddProfile(ctx, &proto.AddProfileRequest{
		ProfileName: profileName,
		Username:    username,
	})
	if err != nil {
		return "", fmt.Errorf("add profile failed: %w", err)
	}

	return profilemanager.ID(resp.Id), nil
}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Retry with a simple alphanumeric profile name to rule out validation
  2. Check the daemon's state directory permissions (usually /var/lib/netbird or the user's config dir) and daemon logs
  3. Confirm daemon and CLI versions match (upgrade the service)
  4. If it fails only via `up --profile`, create the profile explicitly with `netbird profile add` to see the same RPC in isolation
Defensive patterns

Strategy: validation

Validate before calling

name := strings.TrimSpace(profileName)
if name == "" || strings.ContainsAny(name, "\x00\n\r\t") {
    return errors.New("profile name must be non-empty printable text")
}

Type guard

func validProfileName(s string) bool {
    return s != "" && !strings.ContainsAny(s, "\x00\n\r\t")
}

Try / catch

resp, err := client.AddProfile(ctx, &proto.AddProfileRequest{ProfileName: name, Username: user})
if err != nil {
    if st, ok := status.FromError(err); ok && st.Code() == codes.Unavailable {
        return fmt.Errorf("daemon restarting during add; retry: %w", err)
    }
    return fmt.Errorf("add profile failed: %w", err)
}

Prevention

When it happens

Trigger: Profile name rejected by daemon validation (empty, control characters, bad length); daemon's profile store unwritable; daemon restarted mid-call (Unavailable); CLI/daemon version skew where AddProfile semantics differ; duplicate handling policy on the daemon.

Common situations: Automating `netbird up --profile <name>` with machine-generated names containing invalid characters; full state directory permissions broken (root-owned after manual sudo use); partial upgrades between CLI and daemon.

Related errors


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