gravitational/teleport · error

repeated attributeType %q, remaining tokens: %s

Error message

repeated attributeType %q, remaining tokens: %s

What it means

parseRDNSequence tracks attribute types already seen across comma-separated RDNs via seenAttrs. When the same attributeType appears twice in distinct RDNs (e.g. 'CN=a,CN=b'), markAttr returns this error. Multi-valued RDNs joined by '+' are allowed, but the same attribute may only appear once per comma-separated component.

Source

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

	}

	dst := &pkix.Name{}
	if tokens.Len() == 0 {
		return dst, nil
	}
	if err := parseRDNSequence(dst, *tokens); err != nil {
		return nil, fmt.Errorf("malformed RDNs: %w", err)
	}
	return dst, nil
}

// parseRDNSequence parses a RelativeDistinguishedName sequence, ie, a sequence
// of AttributeTypeAndValue separated by commas or pluses.
func parseRDNSequence(dst *pkix.Name, tokens tokenList) error {
	seenAttrs := make(map[string]struct{})
	markAttr := func(attr string) error {
		if _, ok := seenAttrs[attr]; ok {
			return fmt.Errorf("repeated attributeType %q, remaining tokens: %s", attr, tokens)
		}
		seenAttrs[attr] = struct{}{}
		return nil
	}

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

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

		switch tok.kind {

View on GitHub (pinned to 1283425b60)

Solutions

  1. Remove the duplicate attributeType from the DN string
  2. Merge values into one attribute where the parser supports lists (e.g. OU=a,OU=b fails too — combine into one value or a multi-valued RDN of the same type)
  3. Move the second value into a different supported attribute (e.g. use OU for additional organization units)
  4. Pre-validate the DN for duplicate keys before passing it to ParseDistinguishedName

Example fix

// before
ParseDistinguishedName("CN=proxy,CN=proxy-alt")
// after
ParseDistinguishedName("CN=proxy")
Defensive patterns

Strategy: validation

Validate before calling

func noDuplicateAttrs(dn string) error {
	seen := map[string]bool{}
	for _, part := range strings.Split(dn, ",") {
		kv := strings.SplitN(strings.TrimSpace(part), "=", 2)
		if len(kv) == 2 {
			if seen[kv[0]] { return fmt.Errorf("duplicate attribute %q in DN", kv[0]) }
			seen[kv[0]] = true
		}
	}
	return nil
}

Try / catch

if err := noDuplicateAttrs(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=server,CN=alias.example.com') — a second CN (or O, OU, etc.) after a comma triggers markAttr. Note the first markAttr error (for the initial attribute) is deliberately discarded (_ = markAttr(prevAttr)), so only repeats from the second RDN onward surface.

Common situations: Templates or configs that concatenate subject components and emit 'O=Org1,O=Org2' instead of using a single multi-valued RDN 'O=Org1+O=Org2' or an OU list; users expecting RFC 4514 behavior where repeated attributes are legal.

Related errors


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