netbirdio/netbird · error

parse custom DNS address: %v

Error message

parse custom DNS address: %v

What it means

Thrown by the `netbird up` command before any daemon contact, when the --dns-resolver-address flag cannot be parsed. runInDaemonMode calls parseCustomDNSAddress, which only accepts a literal "IP:Port" string or an empty string, and this wrapper adds the 'parse custom DNS address' context. It is pure CLI-side input validation, so the daemon is never reached when it fires.

Source

Thrown at client/cmd/up.go:278

	r := peer.NewRecorder(config.ManagementURL.String())
	r.GetFullStatus()

	connectClient := internal.NewConnectClient(ctx, config, r)
	SetupDebugHandler(ctx, config, r, connectClient, "")

	return connectClient.Run(nil, util.FindFirstLogPath(logFiles))
}

func runInDaemonMode(ctx context.Context, cmd *cobra.Command, pm *profilemanager.ProfileManager, activeProf *profilemanager.Profile, profileSwitched bool) error {
	// Check if deprecated config flag is set and show warning
	if cmd.Flag("config").Changed && configPath != "" {
		cmd.PrintErrf("Warning: Config flag is deprecated on up command, it should be set as a service argument with $NB_CONFIG environment or with \"-config\" flag; netbird service reconfigure --service-env=\"NB_CONFIG=<file_path>\" or netbird service run --config=<file_path>\n")
	}

	customDNSAddressConverted, err := parseCustomDNSAddress(cmd.Flag(dnsResolverAddress).Changed)
	if err != nil {
		return fmt.Errorf("parse custom DNS address: %v", err)
	}

	conn, err := DialClientGRPCServer(ctx, daemonAddr)
	if err != nil {
		//nolint
		return fmt.Errorf("failed to connect to daemon error: %v\n"+
			"If the daemon is not running please run: "+
			"\nnetbird service install \nnetbird service start\n", err)
	}
	defer func() {
		err := conn.Close()
		if err != nil {
			log.Warnf("failed closing daemon gRPC client connection %v", err)
			return
		}
	}()

	client := proto.NewDaemonServiceClient(conn)

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Pass a strict IP:Port value, e.g. `netbird up --dns-resolver-address 8.8.8.8:53`
  2. Pass an explicit empty string (`--dns-resolver-address ""`) to reset to the daemon default
  3. Drop the flag entirely to keep the current profile setting

Example fix

// before
netbird up --dns-resolver-address 8.8.8.8
// after
netbird up --dns-resolver-address 8.8.8.8:53
Defensive patterns

Strategy: validation

Validate before calling

// before invoking `netbird up`, gate on the same rule the CLI applies
if dnsResolverAddress != "" {
	if _, err := netip.ParseAddrPort(dnsResolverAddress); err != nil {
		return fmt.Errorf("--dns-resolver-address must be IP:Port, got %q", dnsResolverAddress)
	}
}

Prevention

When it happens

Trigger: Running `netbird up --dns-resolver-address <value>` where value is neither empty nor parseable by netip.ParseAddrPort (e.g. "8.8.8.8", "localhost:53", "1.2.3.4:99999"). Only fires when the flag was explicitly changed on this invocation.

Common situations: Users porting an old config that used a bare IP without a port, using a hostname instead of an IP, or adding a port outside 0-65535. Also seen after upgrades that changed this flag from host:port tolerant to strict IP:Port.

Related errors


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