netbirdio/netbird · warning

invalid direction: use 'in' or 'out'

Error message

invalid direction: use 'in' or 'out'

What it means

Thrown by tracePacket (client/cmd/trace.go:45), the handler for 'netbird debug trace <direction> <source-ip> <dest-ip>'. args[0] is lowercased and must equal "in" or "out"; anything else is rejected before any daemon call. Pure CLI argument validation - the daemon is never contacted.

Source

Thrown at client/cmd/trace.go:45

	debugCmd.AddCommand(traceCmd)

	traceCmd.Flags().StringP("protocol", "p", "tcp", "Protocol (tcp/udp/icmp)")
	traceCmd.Flags().Uint16("sport", 0, "Source port")
	traceCmd.Flags().Uint16("dport", 0, "Destination port")
	traceCmd.Flags().Uint8("icmp-type", 0, "ICMP type")
	traceCmd.Flags().Uint8("icmp-code", 0, "ICMP code")
	traceCmd.Flags().Bool("syn", false, "TCP SYN flag")
	traceCmd.Flags().Bool("ack", false, "TCP ACK flag")
	traceCmd.Flags().Bool("fin", false, "TCP FIN flag")
	traceCmd.Flags().Bool("rst", false, "TCP RST flag")
	traceCmd.Flags().Bool("psh", false, "TCP PSH flag")
	traceCmd.Flags().Bool("urg", false, "TCP URG flag")
}

func tracePacket(cmd *cobra.Command, args []string) error {
	direction := strings.ToLower(args[0])
	if direction != "in" && direction != "out" {
		return fmt.Errorf("invalid direction: use 'in' or 'out'")
	}

	protocol := cmd.Flag("protocol").Value.String()
	if protocol != "tcp" && protocol != "udp" && protocol != "icmp" {
		return fmt.Errorf("invalid protocol: use tcp/udp/icmp")
	}

	sport, err := cmd.Flags().GetUint16("sport")
	if err != nil {
		return fmt.Errorf("invalid source port: %v", err)
	}
	dport, err := cmd.Flags().GetUint16("dport")
	if err != nil {
		return fmt.Errorf("invalid destination port: %v", err)
	}

	// For TCP/UDP, generate random ephemeral port (49152-65535) if not specified
	if protocol != "icmp" {

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Use exactly 'in' or 'out' as the first positional argument (case-insensitive: 'IN' works)
  2. Check the command examples in 'netbird debug trace --help'

Example fix

// before
Args: cobra.ExactArgs(3),
RunE: tracePacket,

// after: reject bad direction at the Args layer
Args: func(cmd *cobra.Command, args []string) error {
    if len(args) != 3 {
        return fmt.Errorf("requires <direction> <source-ip> <dest-ip>")
    }
    if d := strings.ToLower(args[0]); d != "in" && d != "out" {
        return fmt.Errorf("invalid direction %q: use 'in' or 'out'", args[0])
    }
    return nil
},
Defensive patterns

Strategy: validation

Validate before calling

dir := strings.ToLower(os.Args[1])
if dir != "in" && dir != "out" {
    log.Fatalf("direction must be 'in' or 'out', got %q", os.Args[1])
}
// only then exec netbird debug trace

Type guard

func isTraceDirection(s string) bool {
    d := strings.ToLower(s)
    return d == "in" || d == "out"
}

Prevention

When it happens

Trigger: Invoking 'netbird debug trace ingress 10.0.0.1 10.0.0.2' or with 'IN '/' inbound'/'input' - any first argument whose lowercase form is not exactly 'in' or 'out' (for example 'ingress', 'egress', 'tx', 'rx').

Common situations: Muscle memory from other tools that use ingress/egress or rx/tx terminology; scripts passing a variable that is empty or misspelled.

Related errors


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