apple/pkl · error · ParseException

valid escape sequence

Error message

valid escape sequence

What it means

JSON strings only allow a fixed set of escapes: \" \\ \/ \b \f \n \r \t and \uXXXX. Any other character after a backslash hits the default branch of readEscape and throws expected("valid escape sequence"). This rejects escapes borrowed from other languages, such as \x41, \0, or \' (escaped single quote).

Solutions

  1. Replace the unsupported escape with a valid one: use \' -> ', \x41 -> A or \u0041, \0 -> \u0000.
  2. Re-serialize the data with a real JSON encoder instead of reusing another language's escaping routine.
  3. Search the input for backslashes and audit each escape against the JSON-allowed set.
  4. Catch ParseException and use its position to fix the exact offending escape.

Example fix

// before
String json = "{\"quote\": \\"it\\\\'s\\\\"}"; // \' is not a JSON escape
// after
String json = "{\"quote\": \\"it's\\\\"}"; // ' needs no escaping
Defensive patterns

Strategy: validation

Validate before calling

// Java: detect escapes outside the JSON-allowed set
if (java.util.regex.Pattern.compile("\\\\(?!\"|\\\\|/|b|f|n|r|t|u)").matcher(json).find()) {
  throw new IllegalArgumentException("Invalid JSON escape sequence found");
}

Try / catch

try {
  parser.parse(json);
} catch (ParseException e) {
  if (e.getMessage().contains("valid escape sequence")) {
    throw new IllegalArgumentException("Unsupported escape in JSON string at " + e.getLocation().line + ":" + e.getLocation().column + " — only \" \\ / b f n r t u are allowed", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: parse() on strings containing \' (common when a tool escapes single quotes), \xNN hex escapes, \0, \e, or backslash-escaped characters invented by custom serializers.

Common situations: Output from non-JSON serializers (shell/SQL string escaping reused for JSON), string escaping performed twice or with the wrong escaping function, hand-written config copying escaping habits from other languages.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08). Data as JSON: /api/errors/9cda0ac2d5c58372. Report an issue: GitHub.

Appendix: source

Thrown at pkl-core/src/main/java/org/pkl/core/util/json/JsonParser.java:288

    switch (current) {
      case '"', '/', '\\' -> captureBuffer.append((char) current);
      case 'b' -> captureBuffer.append('\b');
      case 'f' -> captureBuffer.append('\f');
      case 'n' -> captureBuffer.append('\n');
      case 'r' -> captureBuffer.append('\r');
      case 't' -> captureBuffer.append('\t');
      case 'u' -> {
        var hexChars = new char[4];
        for (var i = 0; i < 4; i++) {
          read();
          if (!isHexDigit()) {
            throw expected("hexadecimal digit");
          }
          hexChars[i] = (char) current;
        }
        captureBuffer.append((char) Integer.parseInt(new String(hexChars), 16));
      }
      default -> throw expected("valid escape sequence");
    }
    read();
  }

  private void readNumber() throws IOException {
    handler.startNumber();
    startCapture();
    readChar('-');
    var firstDigit = current;
    if (!readDigit()) {
      throw expected("digit");
    }
    if (firstDigit != '0') {
      //noinspection StatementWithEmptyBody
      while (readDigit()) {}
    }
    readFraction();
    readExponent();

View on GitHub (pinned to f3efcbfc9b)