docker/compose · error

service %q pre_start[%d]: per_replica is not yet supported;

Error message

service %q pre_start[%d]: per_replica is not yet supported; remove per_replica or set it to false

What it means

pre_start hooks currently support only the default per-replica:false mode, where one hook container runs against the first non-running replica's volumes. Setting per_replica: true is rejected up front, before any container I/O, so no partial state is created.

Source

Thrown at pkg/compose/pre_start.go:64

		}
	}
	return pick
}

// runPreStart executes the service's pre_start hooks sequentially, in declared
// order. Each hook runs as an ephemeral container that shares the service
// container's volumes via VolumesFrom and is attached to the same networks.
// A non-zero exit gates service start.
//
// With per_replica: false (the only currently supported mode), the hook sees
// the volumes of the first non-running replica only — anonymous volumes and
// tmpfs mounts are per-replica and not shared. Use named volumes or bind
// mounts for data the hook produces.
func (s *composeService) runPreStart(ctx context.Context, project *types.Project, service types.ServiceConfig, ctr container.Summary, listener api.ContainerEventListener) error {
	// Validate every hook up front so an unsupported entry never triggers any I/O.
	for i, hook := range service.PreStart {
		if hook.PerReplica {
			return fmt.Errorf("service %q pre_start[%d]: per_replica is not yet supported; remove per_replica or set it to false", service.Name, i)
		}
	}
	for i, hook := range service.PreStart {
		if err := s.runPreStartHook(ctx, project, service, ctr, i, hook, listener); err != nil {
			return err
		}
	}
	return nil
}

func (s *composeService) runPreStartHook(
	ctx context.Context, project *types.Project, service types.ServiceConfig,
	ctr container.Summary, index int, hook types.ServiceHook, listener api.ContainerEventListener,
) error {
	created, err := s.createPreStartContainer(ctx, project, service, ctr, hook)
	if err != nil {
		return err
	}

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. Remove per_replica or set it to false in the pre_start entry
  2. Make the hook idempotent so one shared run suffices (use named volumes or binds, not per-replica anonymous volumes)
  3. If per-replica init is a hard requirement, run init logic inside each service container (entrypoint wrapper) instead

Example fix

# before
services:
  app:
    pre_start:
      - command: ./init.sh
        per_replica: true

# after
services:
  app:
    pre_start:
      - command: ./init.sh
        per_replica: false
Defensive patterns

Strategy: validation

Validate before calling

for i, h := range service.PreStart {
    if h.PerReplica {
        return fmt.Errorf("pre_start[%d]: per_replica unsupported on this compose version", i)
    }
}

Prevention

When it happens

Trigger: A service defines pre_start entries with per_replica: true and docker compose up (or any command materializing the service) runs the runPreStart validation loop.

Common situations: Users copying per-replica init patterns from other orchestrators (e.g. init containers per pod); compose files written against a future/experimental schema; docs from a newer compose where the feature landed.

Related errors


AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15). Data as JSON: /api/errors/82b2f753d72c7d28. Report an issue: GitHub.