docker/cli · error

path lacks required file extension (.exe)

Error message

path %q lacks required file extension (.exe)

What it means

Returned by trimExeSuffix (Windows build only) when the plugin filename has no extension or an extension other than .exe (case-insensitive). On Windows, plugin executables must carry the .exe suffix so the manager can strip it to derive the command name.

Solutions

  1. Ensure the Windows plugin artifact has a .exe extension, e.g. docker-foo.exe.
  2. Build the plugin for Windows (GOOS=windows) so the toolchain produces an .exe.
  3. Remove non-.exe files from the Windows plugin search directory.

Example fix

# before
cli-plugins/docker-foo
# after
cli-plugins/docker-foo.exe
Defensive patterns

Strategy: validation

Try / catch

p, err := newPlugin(candidate, cmds)
if err != nil {
    continue
}

Prevention

When it happens

Trigger: On Windows, a plugin candidate file like 'docker-foo' or 'docker-foo.bat' that lacks the .exe extension.

Common situations: A cross-platform plugin distributed as a non-.exe script/binary on Windows, or a file copied without its extension.

Related errors


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

Appendix: source

Thrown at cli-plugins/manager/suffix_windows.go:13

package manager

import (
	"fmt"
	"path/filepath"
	"strings"
)

// This is made slightly more complex due to needing to be case-insensitive.
func trimExeSuffix(s string) (string, error) {
	ext := filepath.Ext(s)
	if ext == "" || !strings.EqualFold(ext, ".exe") {
		return "", fmt.Errorf("path %q lacks required file extension (.exe)", s)
	}
	return strings.TrimSuffix(s, ext), nil
}

func addExeSuffix(s string) string {
	return s + ".exe"
}

View on GitHub (pinned to 4f84911bfe)