gravitational/teleport · error
unknown attributeType %q, remaining tokens: %s
Error message
unknown attributeType %q, remaining tokens: %s
What it means
After passing charset validation, the attribute type must be one of the explicitly supported short names: SERIALNUMBER, CN, OU, O, POSTALCODE, STREET, L, ST, C (common numeric OIDs are also rejected by design — 'use C instead of 2.5.4.6'). Any other well-formed name falls into the default case and produces 'unknown attributeType'.
Source
Thrown at api/utils/pkixname/parser.go:200
dst.SerialNumber = value
case "CN":
dst.CommonName = value
case "OU":
dst.OrganizationalUnit = append(dst.OrganizationalUnit, value)
case "O":
dst.Organization = append(dst.Organization, value)
case "POSTALCODE":
dst.PostalCode = append(dst.PostalCode, value)
case "STREET":
dst.StreetAddress = append(dst.StreetAddress, value)
case "L":
dst.Locality = append(dst.Locality, value)
case "ST":
dst.Province = append(dst.Province, value)
case "C":
dst.Country = append(dst.Country, value)
default:
return "", fmt.Errorf("unknown attributeType %q, remaining tokens: %s", attr, tokens)
}
return attr, nil
}
func parseOIDExtraName(dst *pkix.Name, attr, value string) error {
parts := strings.Split(attr, ".")
oid := make(asn1.ObjectIdentifier, 0, len(parts))
for _, val := range parts {
num, err := strconv.Atoi(val)
if err != nil {
return fmt.Errorf(
"cannot parse OID component %q as int, OID=%q: %w", val, attr, err)
}
oid = append(oid, num)
}
dst.ExtraNames = append(dst.ExtraNames, pkix.AttributeTypeAndValue{
Type: oid,View on GitHub (pinned to 1283425b60)
Solutions
- Rewrite the DN using only supported attributes: CN, O, OU, C, ST, L, STREET, POSTALCODE, SERIALNUMBER
- Replace DC components with O/OU (e.g. 'DC=example,DC=com' -> 'O=example,OU=com' or a single 'O=example.com')
- Replace UID/EMAILADDRESS with a custom numeric OID form (e.g. '0.9.2342.19200300.100.1.1=user') which goes through parseOIDExtraName
- Consult the parser's documented deviations before porting DNs from other tools
Example fix
// before
ParseDistinguishedName("DC=example,DC=com,CN=proxy")
// after
ParseDistinguishedName("O=example.com,CN=proxy") Defensive patterns
Strategy: validation
Validate before calling
var supportedAttrs = map[string]bool{"SERIALNUMBER": true, "CN": true, "OU": true, "O": true, "POSTALCODE": true, "STREET": true, "L": true, "ST": true, "C": true}
func attrsSupported(dn string) error {
for _, part := range strings.Split(dn, ",") {
kv := strings.SplitN(strings.TrimSpace(part), "=", 2)
if len(kv) == 2 && !supportedAttrs[kv[0]] {
return fmt.Errorf("attribute %q not supported; use CN, O, OU, C, ST, L, STREET, POSTALCODE, SERIALNUMBER or a numeric OID", kv[0])
}
}
return nil
} Try / catch
if err := attrsSupported(dn); err != nil { return err }
name, err := pkixname.ParseDistinguishedName(dn)
if err != nil { return fmt.Errorf("invalid DN %q: %w", dn, err) } Prevention
- Restrict DN authoring to the nine supported short attribute names
- Convert LDAP-style DC components to O/OU before parsing
- For rare attributes, use the full numeric OID form so the value lands in ExtraNames
When it happens
Trigger: ParseDistinguishedName('DC=example,DC=com') — DC is not in the switch. Also 'UID=user', 'EMAILADDRESS=a@b.c', 'SN=SurName', or full-word names like 'COMMONNAME=x'.
Common situations: Users copy AD/LDAP-style DNs ('DC=corp,DC=example,DC=com') or RFC 4514 DNs using UID/serialNumber/emailAddress into Teleport config where only the short set is supported.
Related errors
- malformed RDNs: %w
- repeated attributeType %q, remaining tokens: %s
- multi-valued RDN must refer to the same attribute, but found
- not enough tokens to parse AttributeTypeValue, remaining tok
- invalid attributeType (bad character set): %q
AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02).
Data as JSON: /api/errors/bf7854dc2de2e6b6.
Report an issue: GitHub.