{"record":{"id":"1d9a2e49c634db0d","repo":"oobabooga/textgen","slug":"unexpected-end-of-input","errorCode":null,"errorMessage":"unexpected end of input","messagePattern":"unexpected end of input","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"warning","filePath":"modules/grammar/grammar_utils.py","lineNumber":139,"sourceCode":"            return read_hex(src[2:4]), src[4:]\n        elif esc == \"u\":\n            return read_hex(src[2:6]), src[6:]\n        elif esc == \"U\":\n            return read_hex(src[2:10]), src[10:]\n        elif esc in ('\"', \"[\", \"]\", \"\\\\\", \"-\"):\n            return esc, src[2:]\n        elif esc == \"r\":\n            return \"\\r\", src[2:]\n        elif esc == \"n\":\n            return \"\\n\", src[2:]\n        elif esc == \"t\":\n            return \"\\t\", src[2:]\n        elif esc == \"\\\\\":\n            return \"\\\\\", src[2:]\n        raise RuntimeError(\"unknown escape at \" + src)\n    elif src:\n        return src[0], src[1:]\n    raise RuntimeError(\"unexpected end of input\")\n\n\ndef parse_sequence(state, src, rule_name, outbuf, is_nested):\n    out_start_pos = len(outbuf)\n\n    # sequence size, will be replaced at end when known\n    outbuf.append(TO_BE_FILLED_MARKER)\n\n    last_sym_start = len(outbuf)\n    remaining_src = src\n    while remaining_src:\n        if remaining_src[0] == '\"':  # literal string\n            remaining_src = remaining_src[1:]\n            last_sym_start = len(outbuf)\n            while remaining_src[0] != '\"':\n                char, remaining_src = parse_char(remaining_src)\n\n                # each char of a literal is encoded as a \"range\" of char - char","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/oobabooga/textgen/blob/ed888c71f221df552750e1834b3654abab8ae345/modules/grammar/grammar_utils.py#L121-L157","documentation":"Raised by parse_char (modules/grammar/grammar_utils.py:139): the parser is asked for one more character of a quoted literal but the input string is exhausted — typically a literal whose closing quote is missing (or the file was truncated), so the scan runs off the end.","triggerScenarios":"A grammar rule like root ::= \"unterminated — no closing quote before end of file; or an escape such as \\u12 truncated mid-sequence leaving src empty; grammar files with the final line missing its trailing newline/quote after editor truncation.","commonSituations":"Truncated grammar files (partial download, editor cut-off); copy-paste that dropped the closing '\"'; multi-line attempt inside a single-line literal where the quote after the line break is missing.","solutions":["Find the rule indicated by the surrounding parse position and add the missing closing '\"'.","Re-download or re-paste the full grammar if it may be truncated.","End literals before newlines; GBNF literals cannot span lines."],"exampleFix":"// before\nroot ::= \"hello\n\n// after\nroot ::= \"hello\"\n","handlingStrategy":"validation","validationCode":"import re\n\ndef literals_closed(grammar: str) -> bool:\n    # strip comments is hard; approximate: count quotes per line must be even\n    return all(line.count('\"') % 2 == 0\n               for line in grammar.splitlines()\n               if not line.lstrip().startswith('#'))\n","typeGuard":null,"tryCatchPattern":"try:\n    parse_grammar(grammar_text)\nexcept RuntimeError as e:\n    if 'unexpected end of input' in str(e):\n        raise ValueError('Grammar literal is missing its closing quote') from None\n    raise\n","preventionTips":["Run a quote-balance lint on grammar files before loading them.","Never let literals span lines; break the string into two literals.","Check files are complete after download/copy (size or checksum)."],"tags":["grammar","gbnf","syntax-error","eof"],"backgroundTag":null,"analyzedSha":"ed888c71f221df552750e1834b3654abab8ae345","analyzedAt":"2026-08-15T05:24:21.000Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}