docker/cli · error

no variable name on line

Error message

no variable name on line '%s'

What it means

Returned inside parseKeyValueFile for a non-comment, non-empty line whose key (text before the first '=') is empty — i.e. the line starts with '='. kvfile splits on the first '=' and requires a non-empty KEY.

Solutions

  1. Add a non-empty variable name before '=': 'MYVAR=value'.
  2. If the line is meant to be a comment, prefix it with '#'.
  3. Audit templating that produces env files to guarantee a non-empty key.

Example fix

# before (=value)
=postgres://db
# after
DATABASE_URL=postgres://db
Defensive patterns

Strategy: validation

Validate before calling

// Scan for lines that start with '=' (empty key) before kvfile.Parse.
import ("bufio"; "os"; "strings")

func noEmptyKeys(name string) error {
    f, err := os.Open(name)
    if err != nil { return err }
    defer f.Close()
    s := bufio.NewScanner(f)
    for ln := 1; s.Scan(); ln++ {
        t := strings.TrimLeft(s.Text(), " \t")
        if t == "" || strings.HasPrefix(t, "#") { continue }
        if strings.HasPrefix(t, "=") {
            return fmt.Errorf("%s:%d: no variable name on line %q", name, ln, t)
        }
    }
    return s.Err()
}

// if err := noEmptyKeys(file); err != nil { return err }

Try / catch

if _, err := kvfile.Parse(file, nil); err != nil {
    return err // invalid env file (<file>): no variable name on line '...'
}

Prevention

When it happens

Trigger: An --env-file line such as '=value' or '=foo' (nothing before the '='), typically from a typo, a malformed generated file, or an env var whose name was stripped during templating.

Common situations: Template/substitution that produced an empty variable name (e.g. '${EMPTY}=x'), a hand-edited file where the key was deleted but '=' left behind, or a misformatted CSV export.

Related errors


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

Appendix: source

Thrown at pkg/kvfile/kvfile.go:105

		if !utf8.Valid(scannedBytes) {
			return []string{}, fmt.Errorf("invalid utf8 bytes at line %d: %v", currentLine, scannedBytes)
		}
		// We trim UTF8 BOM
		if currentLine == 1 {
			scannedBytes = bytes.TrimPrefix(scannedBytes, utf8bom)
		}
		// trim the line from all leading whitespace first. trailing whitespace
		// is part of the value, and is kept unmodified.
		line := strings.TrimLeftFunc(string(scannedBytes), unicode.IsSpace)

		if len(line) == 0 || line[0] == '#' {
			// skip empty lines and comments (lines starting with '#')
			continue
		}

		key, _, hasValue := strings.Cut(line, "=")
		if len(key) == 0 {
			return []string{}, fmt.Errorf("no variable name on line '%s'", line)
		}

		// leading whitespace was already removed from the line, but
		// variables are not allowed to contain whitespace or have
		// trailing whitespace.
		if strings.ContainsAny(key, whiteSpaces) {
			return []string{}, fmt.Errorf("variable '%s' contains whitespaces", key)
		}

		if hasValue {
			// key/value pair is valid and has a value; add the line as-is.
			lines = append(lines, line)
			continue
		}

		if lookupFn != nil {
			// No value given; try to look up the value. The value may be
			// empty but if no value is found, the key is omitted.

View on GitHub (pinned to 4f84911bfe)