{"record":{"id":"8c42541f03f19650","repo":"gravitational/teleport","slug":"want-closing-quote-found-eof","errorCode":null,"errorMessage":"want closing quote, found EOF","messagePattern":"want closing quote, found EOF","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"api/utils/pkixname/parser.go","lineNumber":587,"sourceCode":"\t}\n\n\t// Input ended, check the final state.\n\tswitch state {\n\tcase tokenizeStateInit:\n\t\t// OK.\n\tcase tokenizeStateNameComponent:\n\t\treturn nil, fmt.Errorf(\"want attributeType, found EOF\")\n\tcase tokenizeStateAttrType:\n\t\treturn nil, fmt.Errorf(\"want attributeType or '=', found EOF\")\n\tcase tokenizeStateAttrTypeEnd:\n\t\treturn nil, fmt.Errorf(\"want '=' attributeValue, found EOF\")\n\tcase tokenizeStateStringStart, tokenizeStateString, tokenizeStateStringEnd:\n\t\t// OK.\n\t\temitBuffer(tokenString)\n\tcase tokenizeStateStringEscape:\n\t\treturn nil, fmt.Errorf(\"want escaped character, found EOF\")\n\tcase tokenizeStateStringQuote:\n\t\treturn nil, fmt.Errorf(\"want closing quote, found EOF\")\n\tcase tokenizeStateStringQuoteEnd:\n\t\t// OK.\n\tdefault:\n\t\t// This should not be reached. All states are handled above.\n\t\treturn nil, fmt.Errorf(\"found EOF (state=%d)\", state)\n\t}\n\n\treturn tokens, nil\n}\n\nfunc isAttrType(r rune) bool {\n\treturn r >= 'A' && r <= 'Z' ||\n\t\tr >= 'a' && r <= 'z' ||\n\t\tr >= '0' && r <= '9' ||\n\t\tr == '-' ||\n\t\tr == '.'\n}\n","sourceCodeStart":569,"sourceCodeEnd":605,"githubUrl":"https://github.com/gravitational/teleport/blob/1283425b60ec5f60d509ba4c791183d452923ff7/api/utils/pkixname/parser.go#L569-L605","documentation":"The DN tokenizer reached EOF while in tokenizeStateStringQuote, meaning a quoted string value inside the distinguished name was opened with '\"' but never closed. RFC 4514-style DN values may be double-quoted; the tokenizer tracks quote state and fails when input ends while still inside quotes.","triggerScenarios":"ParseDistinguishedName with an unbalanced quote, e.g. \"CN=\\\"my server\" or \"OU=\\\"eng,O=corp\" — the opening quote has no matching closing quote before the end of the string.","commonSituations":"Hand-edited TLS/SSH certificate subject fields; DNs pasted from documentation with quotes half-removed; values containing quotes produced by shell interpolation that stripped one of a pair of quotes.","solutions":["Add the missing closing quote: \"CN=\\\"my server\\\"\".","Remove the quotes entirely and escape special characters with backslash instead (RFC 4514 escaping).","Count quote characters (must be even) in a pre-parse sanity check on the DN string."],"exampleFix":"// before\nname, err := pkixname.ParseDistinguishedName(\"CN=\\\"teleport proxy\")\n// after\nname, err := pkixname.ParseDistinguishedName(\"CN=\\\"teleport proxy\\\"\")","handlingStrategy":"validation","validationCode":"func hasBalancedQuotes(dn string) bool {\n\tinQuote, escaped := false, false\n\tfor _, r := range dn {\n\t\tif escaped { escaped = false; continue }\n\t\tif r == '\\\\' { escaped = true; continue }\n\t\tif r == '\"' { inQuote = !inQuote }\n\t}\n\treturn !inQuote && !escaped\n}\nif !hasBalancedQuotes(rawDN) { return errors.New(\"unbalanced quotes in DN\") }","typeGuard":null,"tryCatchPattern":"if err != nil {\n\tif strings.Contains(err.Error(), \"want closing quote\") {\n\t\t// fail fast with the offending DN; do not retry, input is malformed\n\t}\n}","preventionTips":["Prefer RFC 4514 backslash escaping over quoting when generating DNs.","Check for an even count of unescaped '\"' before parsing.","Beware shell single/double quote stripping when DNs come from CLI or scripts."],"tags":["parsing","ldap","dn","quoting"],"backgroundTag":"unterminated-quoted-string","analyzedSha":"1283425b60ec5f60d509ba4c791183d452923ff7","analyzedAt":"2026-09-02T04:06:41.601Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}