docker/compose · error
invalid service %q. Must specify either image or build
Error message
invalid service %q. Must specify either image or build
What it means
Same contract as error 120 but enforced later, in composeService.ensureImagesExists (build/up pipeline): before pulling or building, compose verifies each service declares image, build, or provider. This is the runtime backstop for projects that reach the build phase without passing the earlier api.BuildOptions.Apply validation (e.g. paths that skip Apply).
Source
Thrown at pkg/compose/build.go:112
if len(serviceToBuild) == 0 {
return imageIDs, nil
}
bake, err := buildWithBake(s.dockerCli)
if err != nil {
return nil, err
}
if bake {
return s.doBuildBake(ctx, project, serviceToBuild, options)
}
return s.doBuildClassic(ctx, project, serviceToBuild, options)
}
func (s *composeService) ensureImagesExists(ctx context.Context, project *types.Project, buildOpts *api.BuildOptions, quietPull bool) error {
for name, service := range project.Services {
if service.Provider == nil && service.Image == "" && service.Build == nil {
return fmt.Errorf("invalid service %q. Must specify either image or build", name)
}
}
images, pinnedDigests, err := s.getLocalImagesDigests(ctx, project)
if err != nil {
return err
}
err = tracing.SpanWrapFunc("project/pull", tracing.ProjectOptions(ctx, project),
func(ctx context.Context) error {
return s.pullRequiredImages(ctx, project, images, quietPull)
},
)(ctx)
if err != nil {
return err
}
if buildOpts != nil {View on GitHub (pinned to ddc4b044b6)
Solutions
- Add image: or build: to the named service in compose.yaml
- If the service is external, give it a provider: block
- Load projects with validation enabled (compose-go loader with consistency checks) so the mistake is caught earlier with a clearer message
- Run docker compose config to inspect the effective service definition
Example fix
# before
services:
worker:
command: ["python", "worker.py"]
# after
services:
worker:
build: ./worker
command: ["python", "worker.py"]
Defensive patterns
Strategy: validation
Validate before calling
// Before compose build/up on a programmatically loaded project:
for name, svc := range project.Services {
if svc.Provider == nil && svc.Image == "" && svc.Build == nil {
return fmt.Errorf("service %q cannot be built or pulled: add image/build/provider", name)
}
} Prevention
- Load compose files with the standard loader and validation (docker compose config equivalent) in CI
- When generating projects in code, assert every service has Image or Build before handing it to compose
- Watch for schema typos — unknown keys are silently accepted as extensions
When it happens
Trigger: Calling the build or up API on a project whose service has no image/build/provider — commonly when the project was loaded with loaders that skip validation (WithConsistency off) or constructed programmatically and passed straight to compose.Service.Build/Up.
Common situations: Programmatic users of pkg/compose building a *types.Project by hand; YAML typos (images:) that remove the image key; services intended only as metadata that accidentally stay enabled because their profile is active.
Related errors
- --build and --no-build are incompatible
- --no-build and --watch are incompatible
- invalid service %q. Must specify either image or build
- service %q build configuration does not support platform: %s
- service %q build.platforms does not support value set by DOC
AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15).
Data as JSON: /api/errors/9d4d2f590ad45404.
Report an issue: GitHub.