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
- Use one of: active, pause, drain (case-insensitive).
- Omit --availability to join with the default active state.
- 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
- Reuse the same availability validation for init and join.
- Omit --availability to accept the active default.
- Guard against trailing whitespace/quotes in tokens.
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
- invalid availability
- error reading from STDIN: data is empty
- config file is required
- cannot supply extra formatting options to the pretty…
- other flags may not be combined with --rollback
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 errView on GitHub (pinned to 4f84911bfe)