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

  1. Rewrite the DN using only supported attributes: CN, O, OU, C, ST, L, STREET, POSTALCODE, SERIALNUMBER
  2. Replace DC components with O/OU (e.g. 'DC=example,DC=com' -> 'O=example,OU=com' or a single 'O=example.com')
  3. Replace UID/EMAILADDRESS with a custom numeric OID form (e.g. '0.9.2342.19200300.100.1.1=user') which goes through parseOIDExtraName
  4. 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

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


AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02). Data as JSON: /api/errors/bf7854dc2de2e6b6. Report an issue: GitHub.