docker/cli · error

replicas can only be used with replicated mode

Error message

replicas can only be used with replicated mode

What it means

Thrown by updateReplicas (cli/command/service/update.go:1138) when `--replicas` is changed but the service's Spec.Mode is nil or its Replicated field is nil. The replicas count only exists on the Replicated mode struct; global/global-job/replicated-job modes don't carry a Replicas field (replicated-job uses TotalCompletions, set via scale).

Solutions

  1. Recreate the service in replicated mode if a fixed replica count is desired: `docker service create --mode replicated --replicas N`.
  2. Do not pass `--replicas` to global/global-job services; they scale with node count.
  3. Verify the mode first: `docker service inspect --format '{{json .Spec.Mode}}' <svc>`.

Example fix

// before
docker service update --replicas 3 myservice   # myservice is global

// after
docker service inspect --format '{{json .Spec.Mode}}' myservice
# => {"Global":{}}  -> recreate as replicated, or scale by nodes
Defensive patterns

Strategy: validation

Validate before calling

if flags.Changed(flagReplicas) {
	res, err := apiClient.ServiceInspect(ctx, id, client.ServiceInspectOptions{})
	if err != nil { return err }
	if res.Service.Spec.Mode.Replicated == nil {
		return fmt.Errorf("service %s is not replicated; --replicas unsupported", id)
	}
}

Type guard

func isReplicatedMode(m *swarm.ServiceMode) bool {
	return m != nil && m.Replicated != nil
}

Prevention

When it happens

Trigger: Running `docker service update --replicas N <svc>` on a service whose mode is global, global-job, or otherwise not `replicated`. The `serviceMode.Replicated == nil` check is true and the error returns.

Common situations: Trying to resize a global service through update; a Compose file with `mode: global` but a deploy script that always sets replicas; mode mismatch after a partial migration.

Related errors


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

Appendix: source

Thrown at cli/command/service/update.go:1138

func equalProtocol(prot1, prot2 network.IPProtocol) bool {
	return prot1 == prot2 ||
		(prot1 == "" && prot2 == network.TCP) ||
		(prot2 == "" && prot1 == network.TCP)
}

func equalPublishMode(mode1, mode2 swarm.PortConfigPublishMode) bool {
	return mode1 == mode2 ||
		(mode1 == "" && mode2 == swarm.PortConfigPublishModeIngress) ||
		(mode2 == "" && mode1 == swarm.PortConfigPublishModeIngress)
}

func updateReplicas(flags *pflag.FlagSet, serviceMode *swarm.ServiceMode) error {
	if !flags.Changed(flagReplicas) {
		return nil
	}

	if serviceMode == nil || serviceMode.Replicated == nil {
		return errors.New("replicas can only be used with replicated mode")
	}
	serviceMode.Replicated.Replicas = flags.Lookup(flagReplicas).Value.(*Uint64Opt).Value()
	return nil
}

type hostMapping struct {
	IPAddr string
	Host   string
}

// updateHosts performs a diff between existing host entries, entries to be
// removed, and entries to be added. Host entries preserve the order in which they
// were added, as the specification mentions that in case multiple entries for a
// host exist, the first entry should be used (by default).
//
// Note that, even though unsupported by the CLI, the service specs format
// allow entries with both a _canonical_ hostname, and one or more aliases
// in an entry (IP-address canonical_hostname [alias ...])

View on GitHub (pinned to 4f84911bfe)