gravitational/teleport · error

multi-valued RDN must refer to the same attribute, but found

Error message

multi-valued RDN must refer to the same attribute, but found %q instead of %q, remaining tokens: %s

What it means

Multi-valued RDNs (components joined by '+') are only permitted when every value refers to the same attributeType (a parser deviation from RFC 2253 documented in ParseDistinguishedName). After seeing '+', parseRDNSequence peeks at the next attribute type and rejects it if it differs from the previous one in the current RDN.

Source

Thrown at api/utils/pkixname/parser.go:109

	}
	_ = markAttr(prevAttr)

	for {
		tok, ok := tokens.Peek()
		if !ok {
			return nil // end
		}

		switch tok.kind {
		case tokenPlus:
			tokens.PopSilently()

			// Validate that prevAttr == current attr.
			// If `!ok` just keep going and parseATV() will fail.
			if nextTok, ok := tokens.Peek(); ok &&
				nextTok.kind == tokenAttrType &&
				nextTok.value != prevAttr {
				return fmt.Errorf(
					"multi-valued RDN must refer to the same attribute, but found %q instead of %q, remaining tokens: %s",
					prevAttr,
					nextTok.value,
					tokens,
				)
			}

			prevAttr, err = parseATV(dst, tokens)
			if err != nil {
				return err
			}

		case tokenComma:
			tokens.PopSilently()
			prevAttr, err = parseATV(dst, tokens)
			if err != nil {
				return err
			}

View on GitHub (pinned to 1283425b60)

Solutions

  1. Replace the '+' with a ',' so each attribute becomes its own RDN — but then ensure the attribute type is not repeated (see duplicate-attribute error)
  2. Drop one of the attributes if the differing one is not needed
  3. Only use '+' to give multiple values of the SAME attribute, e.g. 'OU=TeamA+OU=TeamB'
  4. Pre-validate that every '+'-joined component shares one attribute type

Example fix

// before
ParseDistinguishedName("CN=proxy+O=Teleport")
// after
ParseDistinguishedName("CN=proxy") // or "CN=proxy,O=Teleport" if the duplicate rule allows
Defensive patterns

Strategy: validation

Validate before calling

func multiRDNAttrsValid(dn string) error {
	for _, rdn := range strings.Split(dn, ",") {
		attrs := strings.Split(rdn, "+")
		types := map[string]bool{}
		for _, a := range attrs {
			kv := strings.SplitN(strings.TrimSpace(a), "=", 2)
			if len(kv) == 2 { types[kv[0]] = true }
		}
		if len(types) > 1 { return fmt.Errorf("multi-valued RDN %q mixes attribute types", rdn) }
	}
	return nil
}

Try / catch

if err := multiRDNAttrsValid(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('CN=proxy+O=Teleport') — '+' joins CN and O, which are different attribute types, so the parser returns this error with both attribute names and remaining tokens in the message.

Common situations: Users copy real-world X.509 subjects like 'CN=Name+serialNumber=123' or 'OU=Unit1+O=Org' from certificates, assuming standard RFC 4514 multi-valued RDN semantics that this stricter parser does not allow.

Related errors


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