{"record":{"id":"5028259bc5810d99","repo":"karatelabs/karate","slug":"unexpected-character-at-d-d","errorCode":null,"errorMessage":"unexpected character '#' at %d:%d","messagePattern":"unexpected character '#' at (.+?):(.+?)","errorType":"exception","errorClass":"ParserException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/parser/JsLexer.java","lineNumber":673,"sourceCode":"            }\n        }\n        return keywordOrIdent(tokenStart, pos - tokenStart);\n    }\n\n    // `#` + IdentifierName, one token including the hash. A bare `#` has no other\n    // role in the grammar, so anything else is a hard error rather than the lenient\n    // IDENT fallback — a half-lexed `#x` would parse into silently wrong garbage.\n    private TokenType scanPrivateName() {\n        advance();\n        if (pos < length) {\n            char c = source.charAt(pos);\n            if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c == '$'\n                    || (c > 127 && Character.isJavaIdentifierStart(c))) {\n                scanIdentifier();\n                return PRIVATE_NAME;\n            }\n        }\n        throw new ParserException(String.format(\n                \"unexpected character '#' at %d:%d\", tokenLine + 1, tokenCol + 1));\n    }\n\n    private TokenType keywordOrIdent(int start, int len) {\n        // Note: \"this\" is NOT a keyword in the lexer - it's an identifier that gets\n        // special handling in the parser/evaluator. \"void\" lexes as the VOID keyword\n        // so the parser can dispatch it as a unary operator.\n        // Fast path: switch on length first, then first char\n        if (len == 2) {\n            char c0 = source.charAt(start);\n            if (c0 == 'i') {\n                if (source.charAt(start + 1) == 'f') return IF;\n                if (source.charAt(start + 1) == 'n') return IN;\n            } else if (c0 == 'o' && source.charAt(start + 1) == 'f') {\n                return OF;\n            } else if (c0 == 'd' && source.charAt(start + 1) == 'o') {\n                return DO;\n            }","sourceCodeStart":655,"sourceCodeEnd":691,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/parser/JsLexer.java#L655-L691","documentation":"Karate's JS lexer uses `#` only as the start of a private class field/method name (`#name`), which must be followed by a valid identifier start character. A `#` appearing anywhere else — with no identifier, or after a character that cannot start one — is not part of the JS grammar and is rejected at tokenization time.","triggerScenarios":"A bare `#` or `# ` or `#+` in embedded JS (e.g. `* def x = #`); a `#` used as a comment marker (JS comments are `//` or `/* */`, not `#`); `#` intended as a string left unquoted; a private name like `#1x` starting with a non-identifier character.","commonSituations":"Coming from shell/Python habits and using `#` for comments inside JS blocks; placing Karate-style `#string` placeholder markers inside actual JS expression context where they are not valid; pasting URLs (`https://...#frag`) unquoted; private-field syntax `#x` used outside a class body.","solutions":["Quote the `#` text as a string: `'#'` or `'http://x#frag'`.","Replace `#` comments with `//` in JS code.","If a private field was intended, ensure it appears in a class body and `#` is immediately followed by a valid identifier (`#count`).","Remove the stray `#` if it is a leftover from Karate placeholder syntax used in the wrong position."],"exampleFix":"// before\n* def x = #\n// after\n* def x = '#'","handlingStrategy":"validation","validationCode":"// warn about bare # outside strings/class bodies before eval\nif (/(^|[^\\w'\"#/])#(?!\\p{ID_Start})/u.test(script)) console.warn('stray # in JS: ' + script);","typeGuard":null,"tryCatchPattern":"try {\n  def x = eval(script);\n} catch (e) {\n  if (e.message && e.message.indexOf(\"unexpected character '#'\") >= 0) {\n    karate.log('# must be quoted or start a private name at ' + e.message);\n  }\n  throw e;\n}","preventionTips":["Use // or /* */ for comments in JS, never #.","Quote any # text (URLs, placeholders) as a string.","Only use #name private fields inside class bodies.","Recheck scripts converted from shell/Python comment style."],"tags":["javascript","lexer","unexpected-character","private-field"],"backgroundTag":"invalid-identifier-format","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}