gravitational/teleport · error
want escaped character, found EOF
Error message
want escaped character, found EOF
What it means
ParseDistinguishedName's tokenizer reached the end of the input while in tokenizeStateStringEscape, i.e. the DN string ended immediately after a backslash escape character. The parser requires a character after every '\' because escaped runes are how special DN characters (',', '+', '=', etc.) are represented literally. It cannot emit a token, so it fails the whole parse.
Source
Thrown at api/utils/pkixname/parser.go:585
}
}
}
// Input ended, check the final state.
switch state {
case tokenizeStateInit:
// OK.
case tokenizeStateNameComponent:
return nil, fmt.Errorf("want attributeType, found EOF")
case tokenizeStateAttrType:
return nil, fmt.Errorf("want attributeType or '=', found EOF")
case tokenizeStateAttrTypeEnd:
return nil, fmt.Errorf("want '=' attributeValue, found EOF")
case tokenizeStateStringStart, tokenizeStateString, tokenizeStateStringEnd:
// OK.
emitBuffer(tokenString)
case tokenizeStateStringEscape:
return nil, fmt.Errorf("want escaped character, found EOF")
case tokenizeStateStringQuote:
return nil, fmt.Errorf("want closing quote, found EOF")
case tokenizeStateStringQuoteEnd:
// OK.
default:
// This should not be reached. All states are handled above.
return nil, fmt.Errorf("found EOF (state=%d)", state)
}
return tokens, nil
}
func isAttrType(r rune) bool {
return r >= 'A' && r <= 'Z' ||
r >= 'a' && r <= 'z' ||
r >= '0' && r <= '9' ||
r == '-' ||
r == '.'View on GitHub (pinned to 1283425b60)
Solutions
- Remove the trailing backslash or complete the escape sequence (e.g. "CN=foo\\," instead of "CN=foo\\").
- If the backslash is meant literally, double it: "CN=foo\\\\".
- Trim/validate DN strings at the config-loading boundary before passing them to the parser.
Example fix
// before _dn := "CN=service,O=corp\\" name, err := pkixname.ParseDistinguishedName(_dn) // after _dn := strings.TrimRight(rawDN, "\\") // or fix the escape: "CN=service\\,O=corp" name, err := pkixname.ParseDistinguishedName(_dn)
Defensive patterns
Strategy: validation
Validate before calling
func validDNEscapes(dn string) bool {
for i := 0; i < len(dn); i++ {
if dn[i] == '\\' && i == len(dn)-1 {
return false // trailing backslash, nothing to escape
}
if dn[i] == '\\' {
i++ // skip escaped char
}
}
return true
}
if !validDNEscapes(rawDN) { return errors.New("DN ends with incomplete escape sequence") } Try / catch
var name *pkixname.Name
if err := ...; err != nil {
if strings.Contains(err.Error(), "want escaped character") {
// treat DN as corrupt input: reject or sanitize trailing backslash and retry
}
} Prevention
- Never build DNs by naive string concatenation; use a builder that escapes values.
- Trim trailing separators/backslashes from DN strings at config load.
- Unit-test DNs containing escaped characters (\, \+ \= \\).
When it happens
Trigger: Calling ParseDistinguishedName (directly or via pkixname parsing APIs) with a DN whose value ends in a trailing backslash, e.g. "CN=foo\\" or "OU=eng,O=corp\\" — the escape sequence is never completed before EOF.
Common situations: DNs built by string concatenation or template rendering where a trailing separator/backslash is left behind; DNs copy-pasted from shell commands where the trailing backslash was a line continuation; truncated config values or environment variables holding partial DNs.
Related errors
- found EOF (state=%d)
- want closing quote, found EOF
- distinguished name too large, refusing to parse
- unhandled size name: %v
- malformed RDNs: %w
AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02).
Data as JSON: /api/errors/8a1ed15502bd9ea3.
Report an issue: GitHub.