netbirdio/netbird · error

call service down method: %w

Error message

call service down method: %w

What it means

During `netbird profile select`, the daemon reported the peer Connected for the newly selected profile, and the subsequent Down RPC (issued so the old profile's tunnel comes down cleanly before you use the new one) failed. It runs on the same 7s context, so DeadlineExceeded under a slow teardown is the common cause; Unavailable appears if the daemon restarts mid-switch.

Source

Thrown at client/cmd/profile.go:298

		ProfileName: &handle,
		Username:    &currUser.Username,
	})
	if err != nil {
		return wrapAmbiguityError(err, handle)
	}

	if err := profileManager.SwitchProfile(profilemanager.ID(switchResp.Id)); err != nil {
		return err
	}

	status, err := daemonClient.Status(ctx, &proto.StatusRequest{})
	if err != nil {
		return fmt.Errorf("get service status: %w", err)
	}

	if status.Status == string(internal.StatusConnected) {
		if _, err := daemonClient.Down(ctx, &proto.DownRequest{}); err != nil {
			return fmt.Errorf("call service down method: %w", err)
		}
	}

	id := profilemanager.ID(switchResp.Id)
	cmd.Printf("Profile switched to: %s\n", id.ShortID())
	return nil
}

// wrapAmbiguityError turns the daemon's gRPC InvalidArgument errors
// (which carry the resolver's message verbatim) into CLI-friendly text
// that points the user at --show-id.
func wrapAmbiguityError(err error, handle string) error {
	if err == nil {
		return nil
	}
	st, ok := gstatus.FromError(err)
	if !ok {
		return err

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Retry `netbird profile select <handle>` after checking `netbird status`
  2. If status shows Connected with the wrong profile, run `netbird down` then re-select
  3. Inspect daemon logs for the Down failure (interface removal, firewall cleanup)
  4. Avoid concurrent state-changing CLI calls during a switch
Defensive patterns

Strategy: retry

Validate before calling

# Before switching away from a connected profile, confirm daemon health
netbird status >/dev/null || exit 1
netbird profile select <handle> || netbird profile select <handle>  # one retry after settle

Try / catch

if _, err := daemonClient.Down(ctx, &proto.DownRequest{}); err != nil {
    if errors.Is(ctx.Err(), context.DeadlineExceeded) {
        return fmt.Errorf("switch succeeded but teardown timed out; run `netbird down` if the old tunnel persists")
    }
    return fmt.Errorf("call service down method: %w", err)
}

Prevention

When it happens

Trigger: Interface/firewall teardown taking longer than the remaining 7s budget; daemon restarting while switching; old profile's connection stuck so Down blocks; concurrent CLI command holding the daemon busy.

Common situations: Switching profiles on loaded machines; switching while the old tunnel is in a bad state; switching immediately after boot; running two CLI commands simultaneously.

Related errors


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