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
- Check the daemon state first: systemctl status netbird (or the platform service manager), and start it if stopped
- 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
- For bundle timeouts, retry with fewer log files (lower --log-file-count flag) or a healthier disk
- 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
- Check service state before invoking daemon-backed commands
- Keep CLI and daemon versions in lockstep across upgrades
- For long operations like debug bundle, pass conservative flags (--log-file-count) to stay under RPC deadlines
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.