docker/cli · error

invalid mount config for type "bind": field Source must not…

Error message

invalid mount config for type "bind": field Source must not be empty

What it means

Thrown by resolveVolumePaths when iterating service volumes and a volume with Type == "bind" has an empty Source field. A bind mount requires a host path to bind into the container; without a source there is nothing to mount. The check happens during path resolution after the compose document is parsed into typed config.

Solutions

  1. Add a concrete host path to the bind volume's source field (absolute path recommended).
  2. If you wanted a Docker-managed volume rather than a host bind, remove 'type: bind' (or set 'type: volume') and reference a named volume declared under the top-level 'volumes:' key.
  3. Ensure any interpolation variable used for source is actually set, or provide a default: 'source: ${HOST_PATH:-./data}'.

Example fix

# before
services:
  app:
    volumes:
      - type: bind
        target: /data
# after
services:
  app:
    volumes:
      - type: bind
        source: ./data
        target: /data
Defensive patterns

Strategy: validation

Validate before calling

// Reject bind volumes with an empty source before calling loader.Load.
for _, svc := range config.Services {
    for _, v := range svc.Volumes {
        if v.Type == "bind" && strings.TrimSpace(v.Source) == "" {
            return fmt.Errorf("service %q has a bind volume with empty source", svc.Name)
        }
    }
}

Type guard

func hasBindSource(v types.ServiceVolumeConfig) bool {
    return v.Type != "bind" || v.Source != ""
}

Prevention

When it happens

Trigger: A service declares a volume entry with type: bind (or a long-form volumes entry missing the source) but no source path. Mixing a short-syntax anonymous volume (intended as a named/anonymous volume) while forcing type: bind. A templating step that omits the source when a variable is unset.

Common situations: Authoring 'volumes: - type: bind target: /data' and forgetting the 'source:' line. An env-var-driven source like 'source: ${HOST_PATH}' where HOST_PATH is empty, leaving source blank after interpolation. Copying a named-volume snippet and switching type to bind without adding a host path.

Related errors


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

Appendix: source

Thrown at cli/compose/loader/loader.go:493

			envVars = append(envVars, fileVars...)
		}
		updateEnvironment(environment,
			opts.ConvertKVStringsToMapWithNil(envVars), lookupEnv)
	}

	updateEnvironment(environment, serviceConfig.Environment, lookupEnv)
	serviceConfig.Environment = environment
	return nil
}

func resolveVolumePaths(volumes []types.ServiceVolumeConfig, workingDir string, lookupEnv template.Mapping) error {
	for i, volume := range volumes {
		if volume.Type != "bind" {
			continue
		}

		if volume.Source == "" {
			return errors.New(`invalid mount config for type "bind": field Source must not be empty`)
		}

		filePath := expandUser(volume.Source, lookupEnv)
		// Check if source is an absolute path (either Unix or Windows), to
		// handle a Windows client with a Unix daemon or vice-versa.
		//
		// Note that this is not required for Docker for Windows when specifying
		// a local Windows path, because Docker for Windows translates the Windows
		// path into a valid path within the VM.
		if !path.IsAbs(filePath) && !isAbs(filePath) {
			filePath = absPath(workingDir, filePath)
		}
		volume.Source = filePath
		volumes[i] = volume
	}
	return nil
}

View on GitHub (pinned to 4f84911bfe)