netbirdio/netbird · error

connect to daemon: %w

Error message

connect to daemon: %w

What it means

DialClientGRPCServer could not establish a gRPC connection to the daemon. It calls grpc.DialContext with WithBlock under a 10-second timeout, targeting whatever --daemon-addr resolves to via daddr.DialTarget (unix socket, npipe on Windows, or TCP), so this error means 'no daemon answered within 10s'. The underlying dial error is wrapped with %w.

Source

Thrown at client/cmd/expose.go:175

	if err != nil {
		return err
	}

	cmd.Root().SilenceUsage = true

	ctx, cancel := context.WithCancel(cmd.Context())
	defer cancel()

	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
	go func() {
		<-sigCh
		cancel()
	}()

	conn, err := DialClientGRPCServer(ctx, daemonAddr)
	if err != nil {
		return fmt.Errorf("connect to daemon: %w", err)
	}
	defer func() {
		if err := conn.Close(); err != nil {
			log.Debugf("failed to close daemon connection: %v", err)
		}
	}()

	client := proto.NewDaemonServiceClient(conn)

	protocol, err := toExposeProtocol(exposeProtocol)
	if err != nil {
		return err
	}

	req := &proto.ExposeServiceRequest{
		Port:       uint32(port),
		Protocol:   protocol,
		Pin:        exposePin,

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Start or install the daemon: `sudo systemctl start netbird` (Windows: `sc start netbird`; if missing: `netbird service install`) and re-run `netbird expose`
  2. Sanity-check with `netbird status` — if that also fails, the daemon is down; read its logs (journalctl -u netbird / client.log) to find why
  3. If --daemon-addr or NB_DAEMON_ADDR is set, verify it exactly matches the daemon's serve address or unset it to use the default
  4. If the socket file is missing while the service claims active, restart the service so it recreates it
Defensive patterns

Strategy: retry

Validate before calling

# fail fast if the daemon is not there before invoking expose
systemctl is-active --quiet netbird || echo "netbird service not active; start it first"
netbird status >/dev/null 2>&1 || echo "daemon not answering on its socket"

Try / catch

conn, err := DialClientGRPCServer(ctx, daemonAddr)
if err != nil {
	if ctx.Err() == context.Canceled {
		return fmt.Errorf("interrupted before connecting: %w", err)
	}
	// 10s blocking dial timed out: daemon absent or wrong address; fix that, do not loop blindly
	return fmt.Errorf("connect to daemon (is the netbird service running at %s?): %w", daemonAddr, err)
}

Prevention

When it happens

Trigger: The netbird service is not installed or not started; the daemon crashed; --daemon-addr / NB_DAEMON_ADDR points at a socket or host the daemon is not serving; the unix socket file was deleted (e.g. tmpfs cleanup of /var/run); permission denied on the socket; a SIGINT/SIGTERM arrived before or during the dial and canceled the context.

Common situations: Fresh machine before `netbird service install`/start; systemd unit in failed state; containers or minimal VMs with only the CLI; running as a user without access to the daemon socket; boot race where the command runs before the service.

Related errors


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