gravitational/teleport · error

want escaped character, found EOF

Error message

want escaped character, found EOF

What it means

ParseDistinguishedName's tokenizer reached the end of the input while in tokenizeStateStringEscape, i.e. the DN string ended immediately after a backslash escape character. The parser requires a character after every '\' because escaped runes are how special DN characters (',', '+', '=', etc.) are represented literally. It cannot emit a token, so it fails the whole parse.

Source

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

			}
		}
	}

	// Input ended, check the final state.
	switch state {
	case tokenizeStateInit:
		// OK.
	case tokenizeStateNameComponent:
		return nil, fmt.Errorf("want attributeType, found EOF")
	case tokenizeStateAttrType:
		return nil, fmt.Errorf("want attributeType or '=', found EOF")
	case tokenizeStateAttrTypeEnd:
		return nil, fmt.Errorf("want '=' attributeValue, found EOF")
	case tokenizeStateStringStart, tokenizeStateString, tokenizeStateStringEnd:
		// OK.
		emitBuffer(tokenString)
	case tokenizeStateStringEscape:
		return nil, fmt.Errorf("want escaped character, found EOF")
	case tokenizeStateStringQuote:
		return nil, fmt.Errorf("want closing quote, found EOF")
	case tokenizeStateStringQuoteEnd:
		// OK.
	default:
		// This should not be reached. All states are handled above.
		return nil, fmt.Errorf("found EOF (state=%d)", state)
	}

	return tokens, nil
}

func isAttrType(r rune) bool {
	return r >= 'A' && r <= 'Z' ||
		r >= 'a' && r <= 'z' ||
		r >= '0' && r <= '9' ||
		r == '-' ||
		r == '.'

View on GitHub (pinned to 1283425b60)

Solutions

  1. Remove the trailing backslash or complete the escape sequence (e.g. "CN=foo\\," instead of "CN=foo\\").
  2. If the backslash is meant literally, double it: "CN=foo\\\\".
  3. Trim/validate DN strings at the config-loading boundary before passing them to the parser.

Example fix

// before
_dn := "CN=service,O=corp\\"
name, err := pkixname.ParseDistinguishedName(_dn)
// after
_dn := strings.TrimRight(rawDN, "\\") // or fix the escape: "CN=service\\,O=corp"
name, err := pkixname.ParseDistinguishedName(_dn)
Defensive patterns

Strategy: validation

Validate before calling

func validDNEscapes(dn string) bool {
	for i := 0; i < len(dn); i++ {
		if dn[i] == '\\' && i == len(dn)-1 {
			return false // trailing backslash, nothing to escape
		}
		if dn[i] == '\\' {
			i++ // skip escaped char
		}
	}
	return true
}
if !validDNEscapes(rawDN) { return errors.New("DN ends with incomplete escape sequence") }

Try / catch

var name *pkixname.Name
if err := ...; err != nil {
	if strings.Contains(err.Error(), "want escaped character") {
		// treat DN as corrupt input: reject or sanitize trailing backslash and retry
	}
}

Prevention

When it happens

Trigger: Calling ParseDistinguishedName (directly or via pkixname parsing APIs) with a DN whose value ends in a trailing backslash, e.g. "CN=foo\\" or "OU=eng,O=corp\\" — the escape sequence is never completed before EOF.

Common situations: DNs built by string concatenation or template rendering where a trailing separator/backslash is left behind; DNs copy-pasted from shell commands where the trailing backslash was a line continuation; truncated config values or environment variables holding partial DNs.

Related errors


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