{"record":{"id":"9ce2a44810381ddb","repo":"oobabooga/textgen","slug":"expecting-name-at-src","errorCode":null,"errorMessage":"expecting name at {src}","messagePattern":"expecting name at (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"warning","filePath":"modules/grammar/grammar_utils.py","lineNumber":99,"sourceCode":"    \"\"\"\n    pos = 0\n    while pos < len(src) and (src[pos].isspace() or src[pos] == \"#\"):\n        if src[pos] == \"#\":\n            while pos < len(src) and src[pos] not in (\"\\r\", \"\\n\"):\n                pos += 1\n        else:\n            if not newline_ok and src[pos] in (\"\\r\", \"\\n\"):\n                break\n            pos += 1\n    return src[pos:]\n\n\ndef parse_name(src):\n    pos = 0\n    while pos < len(src) and is_word_char(src[pos]):\n        pos += 1\n    if pos == 0:\n        raise RuntimeError(\"expecting name at \" + src)\n    return src[:pos], src[pos:]\n\n\ndef read_hex(s):\n    val = 0\n    for c in s:\n        val = (val << 4) + hex_to_int(c)\n    return chr(val)\n\n\ndef parse_char(src):\n    \"\"\"\n    parse the leading char from the input string\n    :param src:\n    :return: char, remaining_src\n    \"\"\"\n\n    # if we have a backslash, it's maybe an escape","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/oobabooga/textgen/blob/ed888c71f221df552750e1834b3654abab8ae345/modules/grammar/grammar_utils.py#L81-L117","documentation":"Raised by parse_name (modules/grammar/grammar_utils.py:99) when the GBNF parser expects a rule name (at the start of a rule, or after '(' grouping / '*' repetition context) but the next characters contain no word characters ([alnum-_]). This is a grammar syntax error, not a generation-time error.","triggerScenarios":"A grammar rule line starting with '::=' (name missing), e.g. '::= \"a\"'; two consecutive operators like 'a* *'; an empty rule ' ::= ...'; leftover junk where the parser expects the next rule name after a newline.","commonSituations":"Hand-edited grammars where a rule name was deleted; missing newline separating rules so one rule's tail is parsed as the next rule's name; comment syntax misuse (comments need '#', not '//'); CRLF/stray characters corrupting rule starts.","solutions":["Look at the src snippet echoed in the message — it shows the exact text where a name was expected; fix or delete it.","Ensure every rule has the form 'name ::= alternates' and rules are separated by newlines.","Validate the grammar in isolation (e.g. via llama.cpp's grammar compiler or a small python driver around modules/grammar) before passing it to generation."],"exampleFix":"// before\nroot ::= \"a\"\n::= \"b\"\n\n// after\nroot ::= \"a\"\nalt ::= \"b\"\n","handlingStrategy":"validation","validationCode":"import re\n\nRULE_LINE = re.compile(r'^\\s*[A-Za-z0-9_-]+\\s*::=')\n\ndef rule_lines_have_names(grammar: str) -> list[int]:\n    return [i for i, line in enumerate(grammar.splitlines(), 1)\n            if line.strip() and not line.lstrip().startswith('#')\n            and not RULE_LINE.match(line)]\n","typeGuard":"def looks_like_gbnf(grammar: str) -> bool:\n    lines = [l for l in grammar.splitlines() if l.strip() and not l.lstrip().startswith('#')]\n    return bool(lines) and all(RULE_LINE.match(l) for l in lines)\n","tryCatchPattern":"try:\n    parse_grammar(grammar_text)\nexcept RuntimeError as e:\n    # message echoes the offending src; surface it to the grammar author\n    raise ValueError(f'GBNF syntax error: {e}') from None\n","preventionTips":["Validate rule shape ('name ::= ...') on every non-comment line before use.","Separate rules with real newlines; avoid joining rules on one line.","Use '#' for comments — '//' is not GBNF and corrupts the next name."],"tags":["grammar","gbnf","syntax-error","validation"],"backgroundTag":null,"analyzedSha":"ed888c71f221df552750e1834b3654abab8ae345","analyzedAt":"2026-08-15T05:24:21.000Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}