{"record":{"id":"0f341ee0ec955cef","repo":"docker/compose","slug":"healthcheck-start-interval-requires-healthcheck-st","errorCode":null,"errorMessage":"healthcheck.start_interval requires healthcheck.start_period to be set","messagePattern":"healthcheck\\.start_interval requires healthcheck\\.start_period to be set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/compose/convert.go","lineNumber":74,"sourceCode":"\tif check.Timeout != nil {\n\t\ttimeout = time.Duration(*check.Timeout)\n\t}\n\tif check.StartPeriod != nil {\n\t\tperiod = time.Duration(*check.StartPeriod)\n\t}\n\tif check.Retries != nil {\n\t\tretries = int(*check.Retries)\n\t}\n\ttest := check.Test\n\tif check.Disable {\n\t\ttest = []string{\"NONE\"}\n\t}\n\tvar startInterval time.Duration\n\tif check.StartInterval != nil {\n\t\tstartInterval = time.Duration(*check.StartInterval)\n\t\tif check.StartPeriod == nil {\n\t\t\t// see https://github.com/moby/moby/issues/48874\n\t\t\treturn nil, errors.New(\"healthcheck.start_interval requires healthcheck.start_period to be set\")\n\t\t}\n\t}\n\treturn &container.HealthConfig{\n\t\tTest:          test,\n\t\tInterval:      interval,\n\t\tTimeout:       timeout,\n\t\tStartPeriod:   period,\n\t\tStartInterval: startInterval,\n\t\tRetries:       retries,\n\t}, nil\n}\n\n// ToSeconds convert into seconds\nfunc ToSeconds(d *compose.Duration) *int {\n\tif d == nil {\n\t\treturn nil\n\t}\n\ts := int(time.Duration(*d).Seconds())","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/docker/compose/blob/ddc4b044b62e9f715212ea4143fa830fac76382f/pkg/compose/convert.go#L56-L92","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add an explicit start_period to the healthcheck, e.g. `start_period: 10s`, alongside start_interval.","If the fast-fail startup probing is not needed, remove start_interval entirely.","Keep both values tuned together (start_interval typically smaller than start_period) when you need quick failure detection during startup."],"exampleFix":"# before\nservices:\n  web:\n    healthcheck:\n      test: [\"CMD\", \"curl\", \"-f\", \"http://localhost\"]\n      interval: 30s\n      start_interval: 5s\n\n# after\nservices:\n  web:\n    healthcheck:\n      test: [\"CMD\", \"curl\", \"-f\", \"http://localhost\"]\n      interval: 30s\n      start_period: 30s\n      start_interval: 5s","handlingStrategy":"validation","validationCode":"# fail fast on start_interval without start_period\nif grep -q 'start_interval:' compose.yaml && ! grep -q 'start_period:' compose.yaml; then\n  echo \"healthcheck.start_interval requires start_period\" >&2\n  exit 1\nfi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set start_period whenever you set start_interval (mobu/moby#48874 constraint).","Run docker compose config in CI to catch invalid healthcheck pairs before deploy."],"tags":["healthcheck","compose-file","validation","convert"],"backgroundTag":null,"analyzedSha":"ddc4b044b62e9f715212ea4143fa830fac76382f","analyzedAt":"2026-08-15T13:31:42.319Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}