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" + line

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Delete whitespace immediately after '=': `KEY=value`
  2. If the value genuinely starts with spaces, quote it: `KEY=" padded"` — quoted values are supported and preserve inner whitespace
  3. 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

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


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/bcd675df81c4d541. Report an issue: GitHub.