docker/cli · error
no files specified
Error message
no files specified
What it means
Returned by loader.Load when configDetails.ConfigFiles is empty. Load requires at least one config file to merge and interpolate; with zero files there is nothing to parse. This is an explicit guard before the load loop begins processing.
Solutions
- Ensure at least one types.ConfigFile (or the default docker-compose.yaml) is appended to configDetails.ConfigFiles before calling Load.
- If reading from stdin, add a ConfigFile with Filename set to '-' and Content set to the stdin bytes.
- Default to the conventional filename ('compose.yaml') when no explicit files are provided.
Example fix
// before
details := types.ConfigDetails{ConfigFiles: []types.ConfigFile{}}
cfg, err := loader.Load(details)
// after
details := types.ConfigDetails{
ConfigFiles: []types.ConfigFile{{Filename: "compose.yaml", Content: data}},
}
cfg, err := loader.Load(details) Defensive patterns
Strategy: validation
Validate before calling
if len(details.ConfigFiles) == 0 {
details.ConfigFiles = append(details.ConfigFiles, types.ConfigFile{
Filename: "compose.yaml",
Content: defaultBytes,
})
}
cfg, err := loader.Load(details) Prevention
- Always default to a conventional filename when no -f is given.
- Assert len(ConfigFiles) > 0 in a helper that wraps Load.
- Unit-test the wrapper with an empty ConfigFiles to confirm it provides a default.
When it happens
Trigger: Constructing a types.ConfigDetails and calling Load without appending any entry to ConfigFiles. A CLI path that resolves --file flags but passes an empty slice because all flags were filtered out or the file did not exist and was silently skipped.
Common situations: A wrapper script building ConfigDetails programmatically forgets to populate ConfigFiles. A -f/--filename argument was consumed but the resolved path list came back empty due to a glob that matched nothing.
Related errors
- compose file contains unsupported options
- config file is required
- specify a Compose file (with --compose-file)
- top-level object must be a mapping
- invalid mount config for type "bind": field Source must not…
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/3fd9ed422ed9eda8.
Report an issue: GitHub.
Appendix: source
Thrown at cli/compose/loader/loader.go:81
var cfg any
if err := yaml.Unmarshal(source, &cfg); err != nil {
return nil, err
}
_, ok := cfg.(map[string]any)
if !ok {
return nil, errors.New("top-level object must be a mapping")
}
converted, err := convertToStringKeysRecursive(cfg, "")
if err != nil {
return nil, err
}
return converted.(map[string]any), nil
}
// Load reads a ConfigDetails and returns a fully loaded configuration
func Load(configDetails types.ConfigDetails, opt ...func(*Options)) (*types.Config, error) {
if len(configDetails.ConfigFiles) < 1 {
return nil, errors.New("no files specified")
}
options := &Options{
Interpolate: &interp.Options{
Substitute: template.Substitute,
LookupValue: configDetails.LookupEnv,
TypeCastMapping: interpolateTypeCastMapping,
},
}
for _, op := range opt {
op(options)
}
configs := []*types.Config{}
var err error
for _, file := range configDetails.ConfigFiles {View on GitHub (pinned to 4f84911bfe)