docker/cli · error
unexpected environment variable
Error message
unexpected environment variable '%s'
What it means
Raised by buildEnvironment when an entry from os.Environ() cannot be split into KEY=VALUE, i.e. it contains no '=' or has an empty key. The environment entries feed Compose variable interpolation, so a malformed entry would break interpolation silently.
Solutions
- Identify the malformed environment string from the error's %s and remove or fix it.
- Ensure any environ slice passed to the loader consists of KEY=VALUE entries with a non-empty KEY.
- Sanitize/normalize environment entries before invoking the stack deploy path.
- On Windows, confirm the malformed entry isn't an MS-DOS '=X' style var; those are filtered, but custom formats may slip through.
Example fix
// before
environ := []string{"FOO", "BAR=baz"} // "FOO" has no '='
// after
environ := []string{"FOO=", "BAR=baz"} // well-formed KEY=VALUE Defensive patterns
Strategy: validation
Validate before calling
// Sanitize an environ slice before passing to the loader
func sanitizeEnviron(env []string) ([]string, error) {
out := make([]string, 0, len(env))
for _, s := range env {
k, v, ok := strings.Cut(s, "=")
if !ok || k == "" {
return nil, fmt.Errorf("malformed environment entry %q", s)
}
out = append(out, k+"="+v)
}
return out, nil
} Type guard
type EnvEntry struct{ Key, Value string }
func parseEnvEntry(s string) (EnvEntry, error) {
k, v, ok := strings.Cut(s, "=")
if !ok || k == "" {
return EnvEntry{}, fmt.Errorf("invalid env %q", s)
}
return EnvEntry{Key: k, Value: v}, nil
} Prevention
- Filter out malformed entries from os.Environ() before composing.
- Add tests covering entries with no '=' or empty keys.
- On Windows, ignore MS-DOS '=X' style vars explicitly.
When it happens
Trigger: An environment variable string passed via os.Environ() (or a test fixture) that has no '=' separator or an empty key. strings.Cut at loader.go:134 returns ok=false for a string with no '=', or k=="" when the part before '=' is empty.
Common situations: Extremely rare in production shells (the OS normally enforces KEY=VALUE); seen in tests with malformed fixtures, on platforms injecting unusual env strings, or when an integration passes a crafted environ slice. Windows '='-prefixed MS-DOS vars are already filtered above this check.
Related errors
- specify a Compose file (with --compose-file)
- compose file contains unsupported options
- invalid image reference for service
- invalid image reference for service
- invalid stack name
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/7ac1bb3bf2d35252.
Report an issue: GitHub.
Appendix: source
Thrown at cli/command/stack/loader.go:136
func buildEnvironment(env []string) (map[string]string, error) {
result := make(map[string]string, len(env))
for _, s := range env {
if runtime.GOOS == "windows" && len(s) > 0 {
// cmd.exe can have special environment variables which names start with "=".
// They are only there for MS-DOS compatibility and we should ignore them.
// See TestBuildEnvironment for examples.
//
// https://ss64.com/nt/syntax-variables.html
// https://devblogs.microsoft.com/oldnewthing/20100506-00/?p=14133
// https://github.com/docker/cli/issues/4078
if s[0] == '=' {
continue
}
}
k, v, ok := strings.Cut(s, "=")
if !ok || k == "" {
return result, fmt.Errorf("unexpected environment variable '%s'", s)
}
// value may be set, but empty if "s" is like "K=", not "K".
result[k] = v
}
return result, nil
}
func loadConfigFiles(filenames []string, stdin io.Reader) ([]composetypes.ConfigFile, error) {
configFiles := make([]composetypes.ConfigFile, 0, len(filenames))
for _, filename := range filenames {
configFile, err := loadConfigFile(filename, stdin)
if err != nil {
return configFiles, err
}
configFiles = append(configFiles, *configFile)
}
View on GitHub (pinned to 4f84911bfe)