netbirdio/netbird · error

address must be in [unix|tcp|npipe]://[path|host:port|name]

Error message

address must be in [unix|tcp|npipe]://[path|host:port|name] format: %q

What it means

parseListenAddress requires scheme://target and splits on the first '://'. The error fires when there is no separator at all, or when either side is empty, i.e. the --daemon-addr value is not shaped like unix:///path, tcp://host:port, or npipe://name.

Source

Thrown at client/cmd/service_socket.go:52

		return &socketListener{Listener: listener, network: network, address: path}, nil
	}

	if network == "unix" {
		removeStaleUnixSocket(address)
	}

	listener, err := net.Listen(network, address)
	if err != nil {
		return nil, err
	}

	return &socketListener{Listener: listener, network: network, address: address}, nil
}

func parseListenAddress(addr string) (string, string, error) {
	network, address, ok := strings.Cut(addr, "://")
	if !ok || network == "" || address == "" {
		return "", "", fmt.Errorf("address must be in [unix|tcp|npipe]://[path|host:port|name] format: %q", addr)
	}

	switch network {
	case "unix", "tcp", "npipe":
		return network, address, nil
	default:
		return "", "", fmt.Errorf("unsupported daemon address protocol: %v", network)
	}
}

func removeStaleUnixSocket(path string) {
	stat, err := os.Lstat(path)
	if err != nil {
		if !os.IsNotExist(err) {
			log.Debugf("stat socket file: %v", err)
		}
		return
	}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Prefix the scheme: unix:///var/run/netbird.sock, tcp://127.0.0.1:8080, or npipe://netbird
  2. Use three slashes for absolute unix paths (unix:// plus /path)
  3. Check shell quoting around the flag value
  4. Reinstall the service with the fixed flag so it persists

Example fix

# before
netbird service run --daemon-addr 127.0.0.1:8080
# after
netbird service run --daemon-addr tcp://127.0.0.1:8080
Defensive patterns

Strategy: validation

Validate before calling

func hasDaemonAddrScheme(a string) bool {
	n, rest, ok := strings.Cut(a, "://")
	return ok && n != "" && rest != ""
}

if !hasDaemonAddrScheme(daemonAddr) {
	return fmt.Errorf("daemon address %q must be scheme://target", daemonAddr)
}

Type guard

func daemonAddrShape(a string) error {
	n, rest, ok := strings.Cut(a, "://")
	if !ok || n == "" || rest == "" {
		return fmt.Errorf("malformed daemon address %q", a)
	}
	return nil
}

Try / catch

network, address, err := parseListenAddress(addr)
if err != nil {
	// shape error: rewrite the flag value; retrying the same value cannot succeed
	return err
}

Prevention

When it happens

Trigger: --daemon-addr /var/run/netbird.sock (no scheme), --daemon-addr 127.0.0.1:8080 (host:port without tcp://), --daemon-addr unix:// (empty path), or an empty value after shell quoting ate the rest.

Common situations: Migrating from older releases whose address had no scheme; copy-pasting a host:port address from another tool's documentation.

Related errors


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