docker/cli · error

invalid image reference for service

Error message

invalid image reference for service %s: %w

What it means

Raised by loadComposeFile when a service has an image value that fails reference.ParseAnyReference, meaning the image string is not a valid OCI/Docker reference (illegal characters, malformed digest/tag, uppercase in domain handling, etc.). The wrapped %w carries the reference parser error.

Solutions

  1. Read the wrapped parser error for the precise malformation.
  2. Correct the image string to the form [registry/]repo[:tag][@digest].
  3. Strip stray whitespace/quotes introduced by templating or env vars.
  4. Validate the reference with `docker pull <image>` before deploying.

Example fix

# before
services:
  web:
    image: myrepo/web: latest   # stray space
# after
services:
  web:
    image: myrepo/web:latest
Defensive patterns

Strategy: validation

Validate before calling

// Validate each service image reference before deploy
for _, svc := range config.Services {
    if _, err := reference.ParseAnyReference(svc.Image); err != nil {
        return fmt.Errorf("service %s invalid image %q: %w", svc.Name, svc.Image, err)
    }
}

Type guard

// Narrow: type that guarantees a parsed reference
type ValidImage struct{ ref reference.AnyReference }

func NewValidImage(s string) (ValidImage, error) {
    r, err := reference.ParseAnyReference(s)
    if err != nil {
        return ValidImage{}, err
    }
    return ValidImage{ref: r}, nil
}

Prevention

When it happens

Trigger: A compose service with `image:` set to a malformed string (e.g. contains spaces, illegal characters, malformed digest, or empty repo). ParseAnyReference at loader.go:59 rejects it and the error wraps the parser detail.

Common situations: Typos in image tags; embedding a digest incorrectly (`image: foo@sha256:not-hex`); trailing whitespace from templating; uppercase letters where lowercase is required; using a bare digest without repo prefix.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/fa24a2fe84be4189. Report an issue: GitHub.

Appendix: source

Thrown at cli/command/stack/loader.go:60

	unsupportedProperties := loader.GetUnsupportedProperties(dicts...)
	if len(unsupportedProperties) > 0 {
		_, _ = fmt.Fprintf(streams.Err(), "Ignoring unsupported options: %s\n\n",
			strings.Join(unsupportedProperties, ", "))
	}

	deprecatedProperties := loader.GetDeprecatedProperties(dicts...)
	if len(deprecatedProperties) > 0 {
		_, _ = fmt.Fprintf(streams.Err(), "Ignoring deprecated options:\n\n%s\n\n",
			propertyWarnings(deprecatedProperties))
	}

	// Validate if each service has a valid image-reference.
	for _, svc := range config.Services {
		if svc.Image == "" {
			return nil, fmt.Errorf("invalid image reference for service %s: no image specified", svc.Name)
		}
		if _, err := reference.ParseAnyReference(svc.Image); err != nil {
			return nil, fmt.Errorf("invalid image reference for service %s: %w", svc.Name, err)
		}
	}

	return config, nil
}

func getDictsFrom(configFiles []composetypes.ConfigFile) []map[string]any {
	dicts := make([]map[string]any, 0, len(configFiles))
	for _, configFile := range configFiles {
		dicts = append(dicts, configFile.Config)
	}

	return dicts
}

func propertyWarnings(properties map[string]string) string {
	msgs := make([]string, 0, len(properties))
	for name, description := range properties {

View on GitHub (pinned to 4f84911bfe)