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

  1. Always pass a non-empty file path or '-' as the second argument: `docker config create NAME path/or/-`.
  2. In code, validate options.file != "" before calling runCreate/readConfigData.
  3. 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

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


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)