{"record":{"id":"812c2cc384c0a669","repo":"nodejs/node","slug":"unexpected-char-r-at-d","errorCode":null,"errorMessage":"unexpected char %r at %d","messagePattern":"unexpected char %r at (.+?)","errorType":"exception","errorClass":"TemplateSyntaxError","httpStatus":null,"severity":"error","filePath":"tools/inspector_protocol/jinja2/lexer.py","lineNumber":737,"sourceCode":"                        stack.append(new_state)\n                    statetokens = self.rules[stack[-1]]\n                # we are still at the same position and no stack change.\n                # this means a loop without break condition, avoid that and\n                # raise error\n                elif pos2 == pos:\n                    raise RuntimeError('%r yielded empty string without '\n                                       'stack change' % regex)\n                # publish new function and start again\n                pos = pos2\n                break\n            # if loop terminated without break we haven't found a single match\n            # either we are at the end of the file or we have a problem\n            else:\n                # end of text\n                if pos >= source_length:\n                    return\n                # something went wrong\n                raise TemplateSyntaxError('unexpected char %r at %d' %\n                                          (source[pos], pos), lineno,\n                                          name, filename)\n","sourceCodeStart":719,"sourceCodeEnd":740,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/tools/inspector_protocol/jinja2/lexer.py#L719-L740","documentation":"The tokenizer loops over a set of regex rules to advance through the source. If no rule matches at the current position and the position is not at end-of-source, the character is untokenizable and Jinja2 raises TemplateSyntaxError('unexpected char %r at %d') with the offending character and byte offset.","triggerScenarios":"A character that does not begin any valid token at that point — for example an unescaped special symbol inside an expression, a stray $ or @ (outside Jinja2's grammar), a control character, or invalid operator combinations.","commonSituations":"Pasting code containing syntax from another template language (Liquid, Twig, Mustache); invisible/control characters in the source; non-breaking spaces or smart quotes copied from a word processor.","solutions":["Inspect the character and offset reported in the message and remove or escape it.","Strip non-ASCII/control characters from the template source (e.g. replace smart quotes and non-breaking spaces).","If the character is intentional inside text, move it out of an expression/tag into literal template text."],"exampleFix":"{# before #}\n{{ user.@name }}\n\n{# after #}\n{{ user.name }}","handlingStrategy":"validation","validationCode":"import unicodedata\n\ndef normalize_template_source(source: str) -> str:\n    # replace smart quotes / non-breaking spaces that confuse the lexer\n    source = source.replace('\\u201c', '\"').replace('\\u201d', '\"')\n    source = source.replace('\\u2018', \"'\").replace('\\u2019', \"'\")\n    source = source.replace('\\u00a0', ' ')\n    if any(unicodedata.category(ch) == 'Cc' and ch not in '\\n\\t' for ch in source):\n        raise ValueError('control characters found in template source')\n    return source","typeGuard":null,"tryCatchPattern":"from jinja2.exceptions import TemplateSyntaxError\ntry:\n    env.parse(source)\nexcept TemplateSyntaxError as e:\n    if 'unexpected char' in str(e):\n        log.error('remove/escape the offending character at offset %s', e.lineno)\n    raise","preventionTips":["Paste templates as plain ASCII/UTF-8 text, not from rich-text editors.","Strip control and zero-width characters before parsing.","Keep foreign template-language syntax out of Jinja2 files."],"tags":["jinja2","syntax","lexer","invalid-character"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}