caddyserver/caddy · error
missing opening heredoc marker on line #%d; must contain onl
Error message
missing opening heredoc marker on line #%d; must contain only alphanumeric characters, dashes and underscores; got empty string
What it means
The lexer saw '<<' followed immediately by a newline: the heredoc opening marker is empty. The marker name (the characters between << and end of line) is required and must be alphanumeric/dash/underscore.
Source
Thrown at caddyconfig/caddyfile/lexer.go:158
if (!quoted && !btQuoted) && (!inHeredoc && !heredocEscaped) &&
len(val) > 1 && string(val[:2]) == "<<" {
// a space means it's just a regular token and not a heredoc
if ch == ' ' {
return makeToken(0), nil
}
// skip CR, we only care about LF
if ch == '\r' {
continue
}
// after hitting a newline, we know that the heredoc marker
// is the characters after the two << and the newline.
// we reset the val because the heredoc is syntax we don't
// want to keep.
if ch == '\n' {
if len(val) == 2 {
return false, fmt.Errorf("missing opening heredoc marker on line #%d; must contain only alphanumeric characters, dashes and underscores; got empty string", l.line)
}
// check if there's too many <
if string(val[:3]) == "<<<" {
return false, fmt.Errorf("too many '<' for heredoc on line #%d; only use two, for example <<END", l.line)
}
heredocMarker = string(val[2:])
if !heredocMarkerRegexp.Match([]byte(heredocMarker)) {
return false, fmt.Errorf("heredoc marker on line #%d must contain only alphanumeric characters, dashes and underscores; got '%s'", l.line, heredocMarker)
}
inHeredoc = true
l.skippedLines++
val = nil
continue
}
val = append(val, ch)View on GitHub (pinned to 50e54ee279)
Solutions
- Add a marker name right after << on the same line (e.g. <<EOF)
- Close the heredoc with a matching line containing only the marker
- Check templating that generates the Caddyfile for empty substitutions
Example fix
# before respond << hi EOF # after respond <<EOF hi EOF
Defensive patterns
Strategy: validation
Validate before calling
if strings.HasSuffix(line, "<<") {
return fmt.Errorf("empty heredoc marker on %q", line)
} Prevention
- Write the marker immediately after << on the same line
- Lint generated Caddyfiles for dangling '<<'
- Test templates that render Caddyfiles with example data
When it happens
Trigger: A line ends with just '<<' — e.g. 'respond <<' with the marker forgotten, or a template placeholder accidentally left in a Caddyfile.
Common situations: Forgetting to name the marker after <<, or envsubst/template rendering that consumed the marker text, leaving bare '<<' at end of line.
Related errors
- incomplete heredoc <<%s on line #%d, expected ending marker
- too many '<' for heredoc on line #%d; only use two, for exam
- heredoc marker on line #%d must contain only alphanumeric ch
- mismatched leading whitespace in heredoc <<%s on line #%d [%
- invalid action type
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/4be1b97096ec46f3.
Report an issue: GitHub.