caddyserver/caddy · error

evaluated placeholder %s%s%s is empty

Error message

evaluated placeholder %s%s%s is empty

What it means

In errOnEmpty mode (ReplaceOrErr with errorOnEmpty), the replacer treats a placeholder that resolves to an empty string as a failure and returns this error naming the placeholder. This is stricter than unknown-key handling: the key was found, but its value is empty, which strict consumers (like dial addresses) consider invalid.

Source

Thrown at replacer.go:269

		}

		// apply any transformations
		if f != nil {
			var err error
			val, err = f(key, val)
			if err != nil {
				return "", err
			}
		}

		// convert val to a string as efficiently as possible
		valStr := ToString(val)

		// write the value; if it's empty, either return
		// an error or write a default value
		if valStr == "" {
			if errOnEmpty {
				return "", fmt.Errorf("evaluated placeholder %s%s%s is empty",
					string(phOpen), key, string(phClose))
			} else if empty != "" {
				sb.WriteString(empty)
			}
		} else {
			sb.WriteString(valStr)
		}

		// advance cursor to end of placeholder
		i = end
		lastWriteCursor = i + 1
	}

	// flush any unwritten remainder
	sb.WriteString(input[lastWriteCursor:])

	return sb.String(), nil
}

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Give the variable a non-empty value, or use Caddy's placeholder default syntax {$VAR:fallback}
  2. Unset the variable entirely if the placeholder should be removed rather than blank
  3. Move the value out of a strict substituted field if empty is legitimately acceptable

Example fix

# before
output net {$LOG_ENDPOINT} # LOG_ENDPOINT=""

# after
output net {$LOG_ENDPOINT:127.0.0.1:514}
Defensive patterns

Strategy: validation

Validate before calling

if v := os.Getenv("LOG_ENDPOINT"); v == "" {
    return fmt.Errorf("LOG_ENDPOINT resolves to empty")
}

Try / catch

if out, err := repl.ReplaceOrErr(in, true, true); err != nil {
    if strings.HasPrefix(err.Error(), "evaluated placeholder") && strings.HasSuffix(err.Error(), "is empty") {
        // supply a default and retry
    }
}

Prevention

When it happens

Trigger: ReplaceOrErr(input, true, true) where a known placeholder expands to "" — e.g. {$EMPTY_VAR} where EMPTY_VAR is exported but set to nothing, feeding output net's address.

Common situations: Environment variables defined but blank (trailing whitespace, empty assignments in .env files); default values not configured for optional variables used in strict config fields.

Related errors


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