netbirdio/netbird · error

create profile: %w

Error message

create profile: %w

What it means

Thrown by switchOrCreateProfile (client/cmd/up.go:168). Flow: switchProfile returned NotFound, then the helper called createProfile and retried switchProfile; when BOTH fail, the create error is wrapped with %w and surfaced here. The comment explains the design: a concurrent run may have created the profile between the NotFound and the create, so the create error is only reported when the retried switch also fails.

Source

Thrown at client/cmd/up.go:168

// switchOrCreateProfile switches the active profile to the one identified by
// handle, creating it first when it does not exist yet. This restores the
// pre-0.73 behaviour where `netbird up --profile <name>` auto-creates a
// missing profile instead of failing.
func switchOrCreateProfile(ctx context.Context, pm *profilemanager.ProfileManager, handle, username string) error {
	resolvedID, err := switchProfile(ctx, handle, username)
	if err != nil {
		st, ok := gstatus.FromError(err)
		if !ok || st.Code() != codes.NotFound {
			return err
		}
		// Don't fail immediately on a create error: a concurrent run may
		// have created the profile between the NotFound above and this
		// call, in which case the retried switch still succeeds. Only
		// surface the create error if the switch also fails.
		_, createErr := createProfile(ctx, handle, username)
		if resolvedID, err = switchProfile(ctx, handle, username); err != nil {
			if createErr != nil {
				return fmt.Errorf("create profile: %w", createErr)
			}
			return err
		}
	}

	if err := pm.SwitchProfile(resolvedID); err != nil {
		return err
	}
	return nil
}

// createProfile dials the daemon and creates a new profile with the given
// display name, returning its generated ID. Use addProfileOnDaemon directly
// when a daemon client is already available to reuse the connection.
func createProfile(ctx context.Context, profileName, username string) (profilemanager.ID, error) {
	conn, err := DialClientGRPCServer(ctx, daemonAddr)
	if err != nil {
		//nolint

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Ensure the daemon is up and healthy, then simply rerun 'netbird up --profile <name>' - the retry path usually succeeds
  2. Check 'netbird service status'/systemctl and the daemon logs for why addProfile failed
  3. Align CLI and daemon versions if the RPC is missing
Defensive patterns

Strategy: retry

Validate before calling

if _, err := DialClientGRPCServer(ctx, daemonAddr); err != nil {
    log.Fatal("daemon unreachable - the profile auto-create path needs it")
}

Prevention

When it happens

Trigger: 'netbird up --profile <name>' where the daemon dial inside createProfile fails (service down - typically surfaces the nested 'failed to connect to daemon' text), or the daemon addProfile RPC rejects the request; simultaneously the retried switch also cannot resolve the handle.

Common situations: Two 'netbird up --profile' invocations racing on one machine while the daemon is flapping or being restarted; daemon running an old version without the profile RPCs.

Related errors


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