{"record":{"id":"eab3675d2675ea16","repo":"apple/pkl","slug":"hexadecimal-digit","errorCode":null,"errorMessage":"hexadecimal digit","messagePattern":"hexadecimal digit","errorType":"exception","errorClass":"ParseException","httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/util/json/JsonParser.java","lineNumber":282,"sourceCode":"    read();\n    return string;\n  }\n\n  private void readEscape() throws IOException {\n    read();\n    switch (current) {\n      case '\"', '/', '\\\\' -> captureBuffer.append((char) current);\n      case 'b' -> captureBuffer.append('\\b');\n      case 'f' -> captureBuffer.append('\\f');\n      case 'n' -> captureBuffer.append('\\n');\n      case 'r' -> captureBuffer.append('\\r');\n      case 't' -> captureBuffer.append('\\t');\n      case 'u' -> {\n        var hexChars = new char[4];\n        for (var i = 0; i < 4; i++) {\n          read();\n          if (!isHexDigit()) {\n            throw expected(\"hexadecimal digit\");\n          }\n          hexChars[i] = (char) current;\n        }\n        captureBuffer.append((char) Integer.parseInt(new String(hexChars), 16));\n      }\n      default -> throw expected(\"valid escape sequence\");\n    }\n    read();\n  }\n\n  private void readNumber() throws IOException {\n    handler.startNumber();\n    startCapture();\n    readChar('-');\n    var firstDigit = current;\n    if (!readDigit()) {\n      throw expected(\"digit\");\n    }","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/util/json/JsonParser.java#L264-L300","documentation":"A \\u escape in a JSON string must be followed by exactly four hexadecimal digits. readEscape reads 4 characters after \\u and calls isHexDigit on each; the first non-hex character (or EOF) triggers expected(\"hexadecimal digit\"). Common with truncated \\u escapes or typos like \\u12g4.","triggerScenarios":"parse() on strings containing \"\\u12\", \"\\uABCG\", \"\\u{\" (template variable eaten by the escape), or a string boundary cutting the escape short.","commonSituations":"Hand-escaped unicode in config files, templating engines interpolating into the middle of a \\u escape, truncated transfer of JSON over a size-limited channel, regex/string processing that mangled escape sequences.","solutions":["Complete the escape with exactly 4 hex digits, e.g. \\u00e9 instead of \\ue or \\u12.","If the character is basic ASCII, drop the escape entirely and write the character directly.","Check for template interpolation colliding with the escape sequence and re-order interpolation/escaping.","Catch ParseException and use the reported position to inspect the malformed \\u sequence."],"exampleFix":"// before\nString json = \"{\\\"ch\\\": \\\"\\\\u12\\\"}\"; // incomplete escape\n// after\nString json = \"{\\\"ch\\\": \\\"\\\\u0012\\\"}\";","handlingStrategy":"validation","validationCode":"// Java: find malformed \\u escapes before parsing\nif (java.util.regex.Pattern.compile(\"\\\\\\\\u(?![0-9a-fA-F]{4})\").matcher(json).find()) {\n  throw new IllegalArgumentException(\"\\\\u escape must be followed by exactly 4 hex digits\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  parser.parse(json);\n} catch (ParseException e) {\n  if (e.getMessage().contains(\"hexadecimal digit\")) {\n    throw new IllegalArgumentException(\"Malformed \\\\uXXXX escape at \" + e.getLocation().line + \":\" + e.getLocation().column, e);\n  }\n  throw e;\n}","preventionTips":["Always write 4 hex digits after \\u (pad with zeros).","Check template interpolation isn't splitting escape sequences.","Prefer writing the literal character instead of manual \\u escapes.","Regex-audit generated files for \\u followed by fewer than 4 hex digits."],"tags":["json","parser","unicode-escape","pkl"],"backgroundTag":"json-parse-error","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}