caddyserver/caddy · error
invalid value on line %d: whitespace before value: '%s'
Error message
invalid value on line %d: whitespace before value: '%s'
What it means
parseEnvFile rejects a value that begins with a space or tab. Because the line is trimmed but the split preserves everything after '=', `KEY= value` yields a value starting with ' ', which Caddy treats as a user error rather than silently trimming (unlike dotenv implementations). Whitespace elsewhere in the value is fine.
Source
Thrown at cmd/main.go:418
// split line into key and value
before, after, isCut := strings.Cut(line, "=")
if !isCut {
return nil, fmt.Errorf("can't parse line %d; line should be in KEY=VALUE format", lineNumber)
}
key, val := before, after
// sometimes keys are prefixed by "export " so file can be sourced in bash; ignore it here
key = strings.TrimPrefix(key, "export ")
// validate key and value
if key == "" {
return nil, fmt.Errorf("missing or empty key on line %d", lineNumber)
}
if strings.Contains(key, " ") {
return nil, fmt.Errorf("invalid key on line %d: contains whitespace: %s", lineNumber, key)
}
if strings.HasPrefix(val, " ") || strings.HasPrefix(val, "\t") {
return nil, fmt.Errorf("invalid value on line %d: whitespace before value: '%s'", lineNumber, val)
}
// remove any trailing comment after value
if commentStart, _, found := strings.Cut(val, "#"); found {
val = strings.TrimRight(commentStart, " \t")
}
// quoted value: support newlines
if strings.HasPrefix(val, `"`) || strings.HasPrefix(val, "'") {
quote := string(val[0])
for !strings.HasSuffix(line, quote) || strings.HasSuffix(line, `\`+quote) {
val = strings.ReplaceAll(val, `\`+quote, quote)
if !scanner.Scan() {
break
}
lineNumber++
line = strings.ReplaceAll(scanner.Text(), `\`+quote, quote)
val += "\n" + lineView on GitHub (pinned to 50e54ee279)
Solutions
- Delete whitespace immediately after '=': `KEY=value`
- If the value genuinely starts with spaces, quote it: `KEY=" padded"` — quoted values are supported and preserve inner whitespace
- Run a quick check: `grep -nE '^[A-Za-z_][A-Za-z0-9_]*=[ \t]' env` to find every offender
Example fix
# before CF_API_TOKEN= v2.0-xyz # after CF_API_TOKEN=v2.0-xyz
Defensive patterns
Strategy: validation
Validate before calling
grep -nE '^[A-Za-z_][A-Za-z0-9_]*=[[:space:]]' env && echo 'whitespace after = found' || echo OK
Prevention
- No space directly after '='
- Quote values that intentionally start with whitespace
When it happens
Trigger: Writing `KEY= value` or `KEY= value` — any whitespace directly after the '=' sign. Very commonly paired with `KEY = value` style, where the leading space of the value is the reported problem.
Common situations: Copy-paste from YAML/JSON where alignment introduces spaces; editors auto-formatting; users expecting dotenv semantics where `KEY= value` trims to `value`.
Related errors
- parsing environment file: %v
- can't parse line %d; line should be in KEY=VALUE format
- missing or empty key on line %d
- invalid key on line %d: contains whitespace: %s
- unmarshaling admin listener address from config: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/bcd675df81c4d541.
Report an issue: GitHub.