docker/compose · error
%q attribute is mandatory to push an image for service %q
Error message
%q attribute is mandatory to push an image for service %q
What it means
Raised by push when the caller set ImageMandatory and a service has no build section and no image attribute (and no provider). Without an image name there is nothing to tag or push, so compose refuses instead of silently skipping; services with build or image are unaffected.
Source
Thrown at pkg/compose/push.go:55
)
func (s *composeService) Push(ctx context.Context, project *types.Project, options api.PushOptions) error {
if options.Quiet {
return s.push(ctx, project, options)
}
return Run(ctx, func(ctx context.Context) error {
return s.push(ctx, project, options)
}, "push", s.events)
}
func (s *composeService) push(ctx context.Context, project *types.Project, options api.PushOptions) error {
eg, ctx := errgroup.WithContext(ctx)
eg.SetLimit(s.maxConcurrency)
for _, service := range project.Services {
if service.Build == nil || service.Image == "" {
if options.ImageMandatory && service.Image == "" && service.Provider == nil {
return fmt.Errorf("%q attribute is mandatory to push an image for service %q", "service.image", service.Name)
}
s.events.On(api.Resource{
ID: service.Name,
Status: api.Done,
Text: "Skipped",
})
continue
}
tags := []string{service.Image}
if service.Build != nil {
tags = append(tags, service.Build.Tags...)
}
for _, tag := range tags {
eg.Go(func() error {
s.events.On(newEvent(tag, api.Working, "Pushing"))
err := s.pushServiceImage(ctx, tag, options.Quiet)
if err != nil {View on GitHub (pinned to ddc4b044b6)
Solutions
- Add an explicit image: <registry>/<repo>:<tag> to the service named in the error.
- If the service should not be pushed, exclude it from the push selection (push specific services only).
- If skipping is acceptable, clear the ImageMandatory option so the service is skipped with a 'Skipped' event instead of failing.
- Add a build: section if the image is meant to be built and pushed under service.image.
Example fix
# before
services:
migrate:
build: . # no image: → push fails when mandatory
# after
services:
migrate:
build: .
image: registry.example.com/team/migrate:1.2.0 Defensive patterns
Strategy: validation
Validate before calling
func allServicesPushable(project *types.Project) error {
for name, svc := range project.Services {
if svc.Image == "" && svc.Build == nil && svc.Provider == nil {
return fmt.Errorf("service %q lacks image and build; not pushable", name)
}
}
return nil
} Try / catch
if err := composeService.Push(ctx, project, api.PushOptions{ImageMandatory: true}); err != nil {
if strings.Contains(err.Error(), "attribute is mandatory to push an image") {
// add image: to the named service or drop ImageMandatory
}
return err
} Prevention
- Give every pushable service an explicit image: tag.
- Run docker compose config and grep for services without image/build before push in CI.
- Scope push commands to the services you actually intend to publish.
When it happens
Trigger: Running push with the image-mandatory option (mirrors docker compose push --ignore-buildable-failure=false semantics) on a project where a service omits image: and is not built from a Dockerfile.
Common situations: Copy-pasted service blocks missing the image key; services intended only as run-once utilities without an image; CI enforcing that every pushable service is explicitly tagged.
Related errors
- --wait-timeout must be a non-negative integer
- --abort-on-container-failure cannot be combined with --abort
- --wait cannot be combined with --abort-on-container-exit, --
- --build and --no-build are incompatible
- --wait cannot be combined with --abort-on-container-exit, --
AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15).
Data as JSON: /api/errors/509af9fbf4012251.
Report an issue: GitHub.