tailscale/tailscale · error

unexpected non-flag arguments

Error message

unexpected non-flag arguments

What it means

'tailscale exit-node up' and 'down' are thin toggles over localClient.SetUseExitNode(wantOn); they accept only flags, no positional arguments. Any extra word is rejected before the daemon call. When turning the node off, the command also tolerates a concurrent 'someone already turned it off' race.

Source

Thrown at cmd/tailscale/cli/exitnode.go:86

						Name:       "disconnect",
						ShortUsage: "tailscale exit-node disconnect",
						ShortHelp:  "Disconnect from current exit node, if any",
						Exec:       exitNodeSetUse(false),
					},
				}
			})()...),
	}
}

var exitNodeArgs struct {
	filter string
	probe  bool
}

func exitNodeSetUse(wantOn bool) func(ctx context.Context, args []string) error {
	return func(ctx context.Context, args []string) error {
		if len(args) > 0 {
			return errors.New("unexpected non-flag arguments")
		}
		err := localClient.SetUseExitNode(ctx, wantOn)
		if err != nil {
			if !wantOn {
				pref, err := localClient.GetPrefs(ctx)
				if err == nil && pref.ExitNodeID == "" {
					// Two processes concurrently turned it off.
					return nil
				}
			}
		}
		return err
	}
}

// runExitNodeList returns a formatted list of exit nodes for a tailnet.
// If the exit node has location and priority data, only the highest
// priority node for each city location is shown to the user.

View on GitHub (pinned to cfe32b8be6)

Solutions

  1. Toggle only: tailscale exit-node up / tailscale exit-node down
  2. To choose a node: tailscale set --exit-node=<name-or-IP> (or tailscale up --exit-node=...)

Example fix

# before
$ tailscale exit-node up my-node
error: unexpected non-flag arguments

# after
$ tailscale set --exit-node=my-node
Defensive patterns

Strategy: validation

Validate before calling

// up/down accept no positionals; steer users to 'set':
if len(args) > 0 {
    return fmt.Errorf("to select an exit node run: tailscale set --exit-node=%s", args[0])
}

Prevention

When it happens

Trigger: Passing an exit node name positionally, e.g. 'tailscale exit-node up my-node'. Selecting a specific exit node is not this command's job.

Common situations: Assuming 'exit-node up <name>' selects that node, mirroring 'tailscale up --exit-node=<name>'.

Related errors


AI-assisted analysis of tailscale/tailscale@cfe32b8be6 (2026-08-15). Data as JSON: /api/errors/5062f8139f24e25b. Report an issue: GitHub.