gravitational/teleport · error
want '+' or ',', found
Error message
want '+' or ',', found %q: %s
What it means
After a closing quote of a quoted attribute value, the tokenizer only accepts a '+' (multi-valued RDN) or ','/' ;' (next RDN). Any other character after the quoted string is rejected. Whitespace is skipped before this check, so the error means real stray content follows the quoted value.
Solutions
- Insert the missing separator ',' or '+' after the quoted value.
- Remove the stray characters following the closing quote.
- Move any extra characters inside the quoted string if they are part of the value: "CN=\"Bob x\"".
Example fix
// before
name, err := pkixname.ParseDistinguishedName("CN=\"Bob\"O=Corp")
// after
name, err := pkixname.ParseDistinguishedName("CN=\"Bob\",O=Corp") Defensive patterns
Strategy: validation
Validate before calling
var afterQuoteRe = regexp.MustCompile(`"[^,+;]`)
func strayAfterQuote(dn string) bool { return afterQuoteRe.MatchString(dn) } Try / catch
name, err := pkixname.ParseDistinguishedName(dn)
if err != nil {
return nil, fmt.Errorf("malformed DN %q: content after quoted value: %w", dn, err)
} Prevention
- Always follow a quoted value with ',' or '+'
- Move extra characters inside the quotes if they belong to the value
- Escape quotes inside values instead of nesting quote groups
When it happens
Trigger: Calling ParseDistinguishedName with content after a quoted value, e.g. "CN=\"Bob\"x", "CN=\"Bob\"=x", or "O=\"Corp\"CN=a" (missing comma).
Common situations: Values with unescaped trailing characters after quotes, hand-written DNs missing a separator between RDNs, or concatenation bugs when building DNs programmatically.
Related errors
- want attributeType, found
- want attributeType or '=', found
- want '=' attributeValue, found
- hexstring not supported
- special character not quoted
AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02).
Data as JSON: /api/errors/7e22d5d83b76a02d.
Report an issue: GitHub.
Appendix: source
Thrown at api/utils/pkixname/parser.go:566
}
case tokenizeStateStringQuote:
switch r {
case '\\':
escapeStart()
case '"':
emitBuffer(tokenString)
state = tokenizeStateStringQuoteEnd
default:
buf.WriteRune(r)
}
case tokenizeStateStringQuoteEnd:
switch r {
case '+', ',', ';':
transitionToNameComponent(r)
default:
return nil, fmt.Errorf("want '+' or ',', found %q: %s", r, errTrace(pos))
}
}
}
// 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:View on GitHub (pinned to 1283425b60)