docker/cli · error

undefined volume

Error message

undefined volume %q

What it means

Returned by handleVolumeToMount when a service mounts a named volume whose source is not in the top-level volumes map and is not anonymous (volume.go:61-64). A non-anonymous volume mount must be declared at the top level (or be external) for the converter to build its Mount.

Solutions

  1. Declare the volume in the top-level `volumes:` block.
  2. If it already exists in Docker, mark it `external: true`.
  3. For an anonymous volume, omit the source (left of the colon).

Example fix

// before
services:
  db:
    image: postgres
    volumes: [pgdata:/var/lib/postgresql/data]
// after
services:
  db:
    image: postgres
    volumes: [pgdata:/var/lib/postgresql/data]
volumes:
  pgdata:
Defensive patterns

Strategy: validation

Validate before calling

func validateNamedVolumes(cfg *composetypes.Config) error {
    for _, svc := range cfg.Services {
        for _, v := range svc.Volumes {
            if v.Type != "volume" && v.Type != "" { continue }
            if v.Source == "" { continue } // anonymous
            if _, ok := cfg.Volumes[v.Source]; !ok {
                return fmt.Errorf("undefined volume %q", v.Source)
            }
        }
    }
    return nil
}

Prevention

When it happens

Trigger: A service volume entry of type volume (the default) with a non-empty `source` that has no entry in the stack volumes map. Reached at volume.go:62 when stackVolumes[volume.Source] is absent.

Common situations: Mounting `myvol:/data` but never declaring `volumes: myvol:`; renamed a volume inconsistently across files; forgot `external: true` for a pre-existing volume.

Related errors


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

Appendix: source

Thrown at cli/compose/convert/volume.go:63

		return mount.Mount{}, errors.New("images options are incompatible with type volume")
	}
	if volume.Tmpfs != nil {
		return mount.Mount{}, errors.New("tmpfs options are incompatible with type volume")
	}
	if volume.Bind != nil {
		return mount.Mount{}, errors.New("bind options are incompatible with type volume")
	}
	if volume.Cluster != nil {
		return mount.Mount{}, errors.New("cluster options are incompatible with type volume")
	}
	// Anonymous volumes
	if volume.Source == "" {
		return result, nil
	}

	stackVolume, exists := stackVolumes[volume.Source]
	if !exists {
		return mount.Mount{}, fmt.Errorf("undefined volume %q", volume.Source)
	}

	result.Source = namespace.Scope(volume.Source)
	result.VolumeOptions = &mount.VolumeOptions{}

	if volume.Volume != nil {
		result.VolumeOptions.NoCopy = volume.Volume.NoCopy
		result.VolumeOptions.Subpath = volume.Volume.Subpath
	}

	if stackVolume.Name != "" {
		result.Source = stackVolume.Name
	}

	// External named volumes
	if stackVolume.External.External {
		return result, nil
	}

View on GitHub (pinned to 4f84911bfe)