{"record":{"id":"de53e08b95e0e2de","repo":"karatelabs/karate","slug":"unexpected-character-u-04x-at-d-d","errorCode":null,"errorMessage":"unexpected character '\\u%04X' at %d:%d","messagePattern":"unexpected character '\\\\u%04X' at (.+?):(.+?)","errorType":"exception","errorClass":"ParserException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/parser/JsLexer.java","lineNumber":889,"sourceCode":"                }\n                return match('=') ? STAR_EQ : STAR;\n\n            case '%':\n                return match('=') ? PERCENT_EQ : PERCENT;\n\n            default:\n                // A non-ASCII char in a category that can never be identifier\n                // material or whitespace is a SyntaxError (§12.2) — e.g. U+180E\n                // Mongolian vowel separator (Cf; whitespace in old Unicode).\n                // Everything else keeps the lenient IDENT fallback: chars the\n                // JDK's Unicode tables don't classify yet (newer-Unicode\n                // ID_Start additions land as UNASSIGNED here) must still lex\n                // as identifiers.\n                if (c > 127) {\n                    int type = Character.getType(c);\n                    if (type == Character.FORMAT || type == Character.CONTROL\n                            || type == Character.LINE_SEPARATOR || type == Character.PARAGRAPH_SEPARATOR) {\n                        throw new ParserException(String.format(\n                                \"unexpected character '\\\\u%04X' at %d:%d\", (int) c, tokenLine + 1, tokenCol + 1));\n                    }\n                }\n                // Unknown character - return as IDENT (will likely cause parse error)\n                return IDENT;\n        }\n    }\n\n    /** StringValue of a string-literal interior: escape sequences decoded to\n     *  their characters. Shared by runtime evaluation (Interpreter) and the\n     *  parser's {@code __proto__}-key comparison (B.3.1 counts escaped\n     *  spellings). */\n    public static String unescapeStringLiteral(String s) {\n        if (s.indexOf('\\\\') == -1) {\n            return s; // no escapes, fast path\n        }\n        StringBuilder sb = new StringBuilder(s.length());\n        for (int i = 0; i < s.length(); i++) {","sourceCodeStart":871,"sourceCodeEnd":907,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/parser/JsLexer.java#L871-L907","documentation":"When a character above ASCII 127 cannot start an identifier or operator, the lexer checks its Unicode category: format, control, line-separator, or paragraph-separator characters are explicitly rejected because Unicode ID_Start/ID_Continue rules make them invalid in source text. The error names the code point and lexer position. Other non-ASCII characters fall through as IDENT and fail later in the parser instead.","triggerScenarios":"Invisible characters pasted into embedded JS: zero-width joiner (U+200D), BOM (U+FEFF) mid-expression, soft hyphen (U+00AD), or U+2028/U+2029 line separators inside a JS expression on one line.","commonSituations":"Copy-pasting code from rich text editors, Slack, PDFs, or web pages that insert zero-width or directional-format characters; hidden BOM after edits; JSON fixtures carrying control characters interpolated into scripts.","solutions":["Delete and retype the region around the reported line:column to remove invisible characters.","Strip format/control characters from the script before use (e.g. replace /[\\u200B-\\u200D\\uFEFF\\u00AD]/g in an editor or build step).","Save the feature file as UTF-8 without BOM.","Paste code through a plain-text editor to drop rich-text artifacts."],"exampleFix":"// before (contains invisible U+200D between 'a' and 'r')\n* def name = va‍rValue\n// after (retyped clean)\n* def name = varValue","handlingStrategy":"validation","validationCode":"// strip invisible format/control characters before eval\nvar clean = script.replace(/[\\u200B-\\u200D\\uFEFF\\u00AD\\u2028\\u2029]/g, '');","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('invisible character detected, clean and retype: ' + e.message);\n  }\n  throw e;\n}","preventionTips":["Paste code through a plain-text editor to drop zero-width/format characters.","Save feature files as UTF-8 without BOM.","Sanitize fixture strings that may carry control characters.","On this error, delete and retype the token at the reported line:column."],"tags":["javascript","lexer","unicode","invisible-characters"],"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-16T19:17:19.609Z"}