docker/cli · error
config file is required
Error message
config file is required
What it means
readConfigData returns errors.New("config file is required") at line 122 when the fileName argument is the empty string. In normal CLI usage this is guarded by Args: cli.ExactArgs(2) on the create command, so this fires primarily for programmatic callers of runCreate/readConfigData who pass an empty file path, or if argument validation is bypassed.
Solutions
- Always pass a non-empty file path or '-' as the second argument: `docker config create NAME path/or/-`.
- In code, validate options.file != "" before calling runCreate/readConfigData.
- Keep the command's Args: cli.ExactArgs(2) intact so the CLI rejects missing args before reaching this code.
Example fix
// before
err := runCreate(ctx, cli, createOptions{name: "cfg", file: ""})
// after
err := runCreate(ctx, cli, createOptions{name: "cfg", file: "./config.txt"}) Defensive patterns
Strategy: validation
Validate before calling
// Programmatic callers: assert a non-empty file before calling runCreate:
if options.file == "" {
return errors.New("config file is required")
} Try / catch
if err := runCreate(ctx, cli, opts); err != nil {
if strings.Contains(err.Error(), "config file is required") {
// prompt user for the file path
}
return err
} Prevention
- Keep Args: cli.ExactArgs(2) on the command so the CLI rejects missing args.
- In code, never pass file == ""; default to "-" or a path.
- Validate options struct before invoking runCreate.
When it happens
Trigger: Calling runCreate with createOptions.file == "" directly; or invoking the create command in a way that skips the ExactArgs(2) check (custom command wiring, tests). The standard `docker config create NAME` (one arg) would be caught earlier by the Args validator.
Common situations: Programmatic use of the config create logic; test fixtures that omit the file; refactors that drop the second positional argument.
Related errors
- error reading from STDIN: data is empty
- cannot supply extra formatting options to the pretty…
- source is required
- error reading content from
- error reading from : data is empty
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/71d83c08acebe1a7.
Report an issue: GitHub.
Appendix: source
Thrown at cli/command/config/create.go:122
// readConfigData reads the config from either stdin or the given fileName.
//
// It reads up to twice the maximum size of the config ([maxConfigSize]),
// just in case swarm's limit changes; this is only a safeguard to prevent
// reading arbitrary files into memory.
func readConfigData(in io.Reader, fileName string) ([]byte, error) {
switch fileName {
case "-":
data, err := io.ReadAll(io.LimitReader(in, 2*maxConfigSize))
if err != nil {
return nil, fmt.Errorf("error reading from STDIN: %w", err)
}
if len(data) == 0 {
return nil, errors.New("error reading from STDIN: data is empty")
}
return data, nil
case "":
return nil, errors.New("config file is required")
default:
// Open file with [FILE_FLAG_SEQUENTIAL_SCAN] on Windows, which
// prevents Windows from aggressively caching it. We expect this
// file to be only read once. Given that this is expected to be
// a small file, this may not be a significant optimization, so
// we could choose to omit this, and use a regular [os.Open].
//
// [FILE_FLAG_SEQUENTIAL_SCAN]: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#FILE_FLAG_SEQUENTIAL_SCAN
f, err := sequential.Open(fileName)
if err != nil {
return nil, fmt.Errorf("error reading from %s: %w", fileName, err)
}
defer f.Close()
data, err := io.ReadAll(io.LimitReader(f, 2*maxConfigSize))
if err != nil {
return nil, fmt.Errorf("error reading from %s: %w", fileName, err)
}
if len(data) == 0 {View on GitHub (pinned to 4f84911bfe)