{"record":{"id":"5cb26ce4307405c3","repo":"gravitational/teleport","slug":"found-eof-state-d","errorCode":null,"errorMessage":"found EOF (state=%d)","messagePattern":"found EOF \\(state=(.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"api/utils/pkixname/parser.go","lineNumber":592,"sourceCode":"\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":574,"sourceCodeEnd":605,"githubUrl":"https://github.com/gravitational/teleport/blob/1283425b60ec5f60d509ba4c791183d452923ff7/api/utils/pkixname/parser.go#L574-L605","documentation":"This is the tokenizer's catch-all: when input ends in any state not explicitly handled (e.g. mid attribute-type, after '=', or after a comma), parsing aborts with \"found EOF (state=%d)\". The state number identifies exactly where the DN grammar was left incomplete. It signals a structurally truncated distinguished name.","triggerScenarios":"ParseDistinguishedName with a DN cut off mid-token, e.g. \"CN\" (no '='), \"CN=\" (no value), or \"CN=a,O\" — any prefix of a valid DN that stops between grammar elements.","commonSituations":"Config values truncated by line-length limits or secrets managers; DNs read from files with missing trailing content; programmatic DN construction that emits separators with empty following components.","solutions":["Complete the DN so it ends after a full attributeType=attributeValue pair.","Use the state value in the message to locate the cut-off point: low states are early in the grammar (attr type), higher states mid-value.","Log/validate the raw DN input at the point it is produced (config load, env var read) to catch truncation at the source."],"exampleFix":"// before\nname, err := pkixname.ParseDistinguishedName(\"CN=proxy,O\") // truncated\n// after\nname, err := pkixname.ParseDistinguishedName(\"CN=proxy,O=corp\")","handlingStrategy":"validation","validationCode":"func looksLikeCompleteDN(dn string) bool {\n\tdn = strings.TrimSpace(dn)\n\tif dn == \"\" || strings.HasSuffix(dn, \",\") || strings.HasSuffix(dn, \"+\") || strings.HasSuffix(dn, \"=\") {\n\t\treturn false\n\t}\n\treturn strings.Contains(dn, \"=\") // must have at least one attr=value pair\n}\nif !looksLikeCompleteDN(rawDN) { return errors.New(\"truncated/incomplete DN\") }","typeGuard":null,"tryCatchPattern":"if err != nil {\n\tif strings.Contains(err.Error(), \"found EOF (state=\") {\n\t\t// log raw DN + state; treat as invalid config input, surface to operator\n\t}\n}","preventionTips":["Validate DN-bearing config values (tls_ca_subject, cert subjects) at startup before use.","Check file/env sources for truncation (line limits, secret-manager clipping).","Keep the full state number from the message when filing bugs — it pinpoints the grammar break."],"tags":["parsing","ldap","dn","eof"],"backgroundTag":"dn-parser-unexpected-eof","analyzedSha":"1283425b60ec5f60d509ba4c791183d452923ff7","analyzedAt":"2026-09-02T04:06:41.601Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}