netbirdio/netbird · error

%s: %w

Error message

%s: %w

What it means

daemonCallError is the CLI's wrapper for daemon RPC failures. If the daemon refused the call because it needs root/administrator, the pre-written privilege guidance is surfaced alone instead (errors.New(guidance)). Otherwise — every non-privilege failure — the error is wrapped as '<context>: <original>', so this exact message shape means a daemon call failed for a reason other than missing privileges: daemon unreachable, RPC deadline, context canceled, or an internal daemon error, with the context string naming the operation (e.g. 'bundle debug').

Source

Thrown at client/cmd/daemon_error.go:23

	"fmt"
	"strings"

	"google.golang.org/genproto/googleapis/rpc/errdetails"
	gstatus "google.golang.org/grpc/status"

	"github.com/netbirdio/netbird/client/internal/ipcauth"
)

// daemonCallError prepares a daemon error for display. A refusal the daemon
// raised because the operation needs root/administrator is already guidance
// written for the user, so it is surfaced on its own instead of buried under the
// gRPC envelope and the name of the RPC that hit it. Anything else is wrapped
// with context as usual.
func daemonCallError(context string, err error) error {
	if guidance, ok := privilegeGuidance(err); ok {
		return errors.New(guidance)
	}
	return fmt.Errorf("%s: %w", context, err)
}

// privilegeGuidance renders the daemon's privilege refusal as a summary and the
// command that performs the operation with the privileges it needs. It reports
// false for any other error.
func privilegeGuidance(err error) (string, bool) {
	info, ok := privilegeErrorInfo(err)
	if !ok {
		return "", false
	}

	summary := info.GetMetadata()[ipcauth.ErrorMetaSummary]
	command := info.GetMetadata()[ipcauth.ErrorMetaCommand]
	if summary == "" {
		// Detail without a summary: fall back to the status message, which
		// carries the same text.
		summary = strings.TrimSpace(gstatus.Convert(err).Message())
	}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Check the daemon state first: systemctl status netbird (or the platform service manager), and start it if stopped
  2. Read the wrapped cause after the colon — 'connection refused' means socket/pipe unreachable, 'context deadline exceeded' means the daemon was slow, and the daemon log holds the detail
  3. For bundle timeouts, retry with fewer log files (lower --log-file-count flag) or a healthier disk
  4. Confirm CLI and daemon versions match (netbird version vs daemon-reported version) after upgrades

Example fix

# before: invoking while the service is down
netbird debug bundle
# -> bundle debug: failed to connect ...

# after: ensure the daemon is up, then bundle
sudo systemctl start netbird && netbird debug bundle
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight the daemon before the RPC:
conn, err := grpc.Dial(daemonSock, grpc.WithBlock(), grpc.WithTimeout(2*time.Second))
if err != nil {
    return fmt.Errorf("daemon not reachable; start the service first")
}

Type guard

// Detect the privilege-refusal path (surfaced without context) vs the wrapped path:
func isPrivilegeRefusal(err error) bool {
    _, ok := privilegeErrorInfo(err)
    return ok
}

Try / catch

// Branch on which of the two shapes daemonCallError produced:
if err := cmd(); err != nil {
    if isPrivilegeRefusal(err) {
        printGuidanceAndExit(err) // message already contains the sudo command
    }
    // wrapped shape '<context>: <cause>'
    log.Errorf("%v", err)
}

Prevention

When it happens

Trigger: netbird debug bundle when the daemon is stopped or the unix socket/named pipe is unreachable (connection refused / timeout inside 'bundle debug: ...'); RPC deadline exceeded on a slow debug-bundle generation; daemon crashed mid-RPC; any future caller of daemonCallError whose RPC fails without the PRIVILEGE_REQUIRED ErrorInfo detail.

Common situations: Service not running on a fresh boot; user lacks permission to talk to the daemon socket (surfaces as a different refusal unless annotated as privilege guidance); very large log sets making DebugBundle exceed the client deadline; mismatched CLI/daemon versions where the RPC method behaves differently.

Related errors


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