docker/compose · error

healthcheck.start_interval requires healthcheck.start_period

Error message

healthcheck.start_interval requires healthcheck.start_period to be set

What it means

When converting a compose healthcheck to the engine's container.HealthConfig, pkg/compose/convert.go maps start_interval; due to moby/moby#48874 the engine misbehaves when start_interval is set without start_period, so compose enforces that start_period must be explicitly set whenever start_interval appears. Absence of start_period with a non-nil start_interval aborts service conversion.

Source

Thrown at pkg/compose/convert.go:74

	if check.Timeout != nil {
		timeout = time.Duration(*check.Timeout)
	}
	if check.StartPeriod != nil {
		period = time.Duration(*check.StartPeriod)
	}
	if check.Retries != nil {
		retries = int(*check.Retries)
	}
	test := check.Test
	if check.Disable {
		test = []string{"NONE"}
	}
	var startInterval time.Duration
	if check.StartInterval != nil {
		startInterval = time.Duration(*check.StartInterval)
		if check.StartPeriod == nil {
			// see https://github.com/moby/moby/issues/48874
			return nil, errors.New("healthcheck.start_interval requires healthcheck.start_period to be set")
		}
	}
	return &container.HealthConfig{
		Test:          test,
		Interval:      interval,
		Timeout:       timeout,
		StartPeriod:   period,
		StartInterval: startInterval,
		Retries:       retries,
	}, nil
}

// ToSeconds convert into seconds
func ToSeconds(d *compose.Duration) *int {
	if d == nil {
		return nil
	}
	s := int(time.Duration(*d).Seconds())

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. Add an explicit start_period to the healthcheck, e.g. `start_period: 10s`, alongside start_interval.
  2. If the fast-fail startup probing is not needed, remove start_interval entirely.
  3. Keep both values tuned together (start_interval typically smaller than start_period) when you need quick failure detection during startup.

Example fix

# before
services:
  web:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost"]
      interval: 30s
      start_interval: 5s

# after
services:
  web:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost"]
      interval: 30s
      start_period: 30s
      start_interval: 5s
Defensive patterns

Strategy: validation

Validate before calling

# fail fast on start_interval without start_period
if grep -q 'start_interval:' compose.yaml && ! grep -q 'start_period:' compose.yaml; then
  echo "healthcheck.start_interval requires start_period" >&2
  exit 1
fi

Prevention

When it happens

Trigger: A service defined as `healthcheck: { test: [...], interval: 10s, start_interval: 5s }` with no `start_period` key, then running docker compose up/create/config on any engine — the guard fires regardless of engine version because compose rejects it up front.

Common situations: Copy-pasting healthcheck snippets from docs that show start_interval alone; migrating compose files from setups that relied on implicit start_period defaults; CI validating compose files failing on previously 'fine' configs after upgrading compose.

Related errors


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