gravitational/teleport · error
not enough tokens to parse AttributeTypeValue, remaining tok
Error message
not enough tokens to parse AttributeTypeValue, remaining tokens: %s
What it means
parseATV expects a complete AttributeTypeAndValue triple (ATTR '=' STRING). Peek3 requires at least 3 remaining tokens; if fewer remain (e.g. a dangling 'CN=' or 'CN' at the end of the DN), the parser cannot form a triple and returns this error. The remaining tokens are included to help locate the truncation.
Source
Thrown at api/utils/pkixname/parser.go:145
}
if err := markAttr(prevAttr); err != nil {
return err
}
default:
// Force an error.
return requireTokenKind(tokenComma, tok, tokens)
}
}
}
// parseATV parses an AttributeTypeAndValue.
//
// Eg: "CN" EQUAL "Llama CA".
func parseATV(dst *pkix.Name, tokens tokenList) (attr string, _ error) {
t1, t2, t3, ok := tokens.Peek3()
if !ok {
return "", fmt.Errorf(
"not enough tokens to parse AttributeTypeValue, remaining tokens: %s",
tokens,
)
}
if err := requireTokenKind(tokenAttrType, t1, tokens); err != nil {
return "", err
}
if err := requireTokenKind(tokenEqual, t2, tokens); err != nil {
return "", err
}
if err := requireTokenKind(tokenString, t3, tokens); err != nil {
return "", err
}
// Pop tokens before returning. We retain the tokens up until the end so
// eventual errors include them in the message.
defer func() {
tokens.PopSilently()View on GitHub (pinned to 1283425b60)
Solutions
- Ensure every component is a full 'ATTR=VALUE' pair including the final one
- Remove dangling/trailing components like a bare 'CN' or 'CN=' with empty value
- Trim trailing commas/semicolons from the DN string before parsing
- Check that template/variable substitution actually filled the last value
Example fix
// before
ParseDistinguishedName("C=US,O=Teleport,CN=")
// after
ParseDistinguishedName("C=US,O=Teleport,CN=proxy") Defensive patterns
Strategy: validation
Validate before calling
func completePairs(dn string) error {
parts := strings.Split(dn, ",")
for i, part := range parts {
kv := strings.SplitN(part, "=", 2)
if len(kv) != 2 || strings.TrimSpace(kv[0]) == "" || kv[1] == "" {
return fmt.Errorf("component %d (%q) is not a complete ATTR=VALUE pair", i, part)
}
}
return nil
} Try / catch
if err := completePairs(dn); err != nil { return err }
name, err := pkixname.ParseDistinguishedName(dn)
if err != nil { return fmt.Errorf("invalid DN %q: %w", dn, err) } Prevention
- Trim trailing commas and stray separators before parsing
- Verify template variables that supply the last component's value are non-empty
- Every component needs all three parts: attribute, '=', value
When it happens
Trigger: DNs ending in a truncated component: 'C=US,O=Teleport,CN' (1 token left) or 'C=US,O=Teleport,CN=' (2 tokens left, empty value still needs the STRING token slot) — Peek3 fails because fewer than 3 tokens remain.
Common situations: Config strings assembled by string concatenation where the last component's value is missing (template variable empty, trailing comma 'C=US,CN=' then split artifacts), or copy-paste truncation in YAML/CLI values.
Related errors
- malformed RDNs: %w
- repeated attributeType %q, remaining tokens: %s
- multi-valued RDN must refer to the same attribute, but found
- invalid attributeType (bad character set): %q
- unknown attributeType %q, remaining tokens: %s
AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02).
Data as JSON: /api/errors/a1045009a4682073.
Report an issue: GitHub.