docker/cli · error

invalid availability

Error message

invalid availability %q, only active, pause and drain are supported

What it means

Returned by 'docker swarm join' when --availability is explicitly set but the value is not active, pause, or drain (case-insensitive). The switch at join.go:61-66 mirrors the init validation.

Solutions

  1. Use one of: active, pause, drain (case-insensitive).
  2. Omit --availability to join with the default active state.
  3. Verify spelling and remove surrounding quotes/spaces.

Example fix

# before
docker swarm join --availability drained --token <tok> 10.0.0.5:2377

# after
docker swarm join --availability drain --token <tok> 10.0.0.5:2377
Defensive patterns

Strategy: validation

Validate before calling

validAvail := map[string]bool{"active": true, "pause": true, "drain": true}
if opts.availability != "" && !validAvail[strings.ToLower(opts.availability)] {
    return fmt.Errorf("invalid availability %q", opts.availability)
}

Type guard

func isValidAvailability(s string) bool {
	switch strings.ToLower(s) {
	case "active", "pause", "drain":
		return true
	}
	return false
}

Prevention

When it happens

Trigger: Running 'docker swarm join --availability <other> --token <t> <mgr>' with an invalid value such as 'drained', 'running', or a typo. Only fires when flags.Changed(flagAvailability) is true.

Common situations: Same vocabulary mistake as init (e.g. 'drained'); copy-pasting a different orchestrator's terminology; whitespace in the value.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/82e459df68365d37. Report an issue: GitHub.

Appendix: source

Thrown at cli/command/swarm/join.go:65

	flags.Var(&opts.listenAddr, flagListenAddr, `Listen address (format: "<ip|interface>[:port]")`)
	flags.StringVar(&opts.advertiseAddr, flagAdvertiseAddr, "", `Advertised address (format: "<ip|interface>[:port]")`)
	flags.StringVar(&opts.dataPathAddr, flagDataPathAddr, "", `Address or interface to use for data path traffic (format: "<ip|interface>")`)
	flags.SetAnnotation(flagDataPathAddr, "version", []string{"1.31"})
	flags.StringVar(&opts.token, flagToken, "", "Token for entry into the swarm")
	flags.StringVar(&opts.availability, flagAvailability, "active", `Availability of the node ("active", "pause", "drain")`)
	return cmd
}

func runJoin(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, opts joinOptions) error {
	apiClient := dockerCLI.Client()

	var availability swarm.NodeAvailability
	if flags.Changed(flagAvailability) {
		switch a := swarm.NodeAvailability(strings.ToLower(opts.availability)); a {
		case swarm.NodeAvailabilityActive, swarm.NodeAvailabilityPause, swarm.NodeAvailabilityDrain:
			availability = a
		default:
			return fmt.Errorf("invalid availability %q, only active, pause and drain are supported", opts.availability)
		}
	}

	_, err := apiClient.SwarmJoin(ctx, client.SwarmJoinOptions{
		JoinToken:     opts.token,
		ListenAddr:    opts.listenAddr.String(),
		AdvertiseAddr: opts.advertiseAddr,
		DataPathAddr:  opts.dataPathAddr,
		RemoteAddrs:   []string{opts.remote},
		Availability:  availability,
	})
	if err != nil {
		return err
	}

	res, err := apiClient.Info(ctx, client.InfoOptions{})
	if err != nil {
		return err

View on GitHub (pinned to 4f84911bfe)