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
- Add a concrete host path to the bind volume's source field (absolute path recommended).
- 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.
- 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
- Always specify 'source' for long-form bind volumes.
- Provide interpolation defaults: ${HOST_PATH:-./data}.
- Run 'docker compose config' to expand and inspect resolved volume sources.
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
- invalid bind source, source cannot be empty
- volume options are incompatible with type bind
- image options are incompatible with type bind
- tmpfs options are incompatible with type bind
- cluster options are incompatible with type bind
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)