{"record":{"id":"9cc1794fb1c329d0","repo":"airbnb/lottie-android","slug":"unterminated-escape-sequence-at-path","errorCode":null,"errorMessage":"Unterminated escape sequence at path {}","messagePattern":"Unterminated escape sequence at path (.+?)","errorType":"exception","errorClass":"EOFException","httpStatus":null,"severity":"error","filePath":"lottie/src/main/java/com/airbnb/lottie/parser/moshi/JsonUtf8Reader.java","lineNumber":996,"sourceCode":"  }\n\n  /**\n   * Unescapes the character identified by the character or characters that immediately follow a\n   * backslash. The backslash '\\' should have already been read. This supports both unicode escapes\n   * \"u000A\" and two-character escapes \"\\n\".\n   *\n   * @throws IOException if any unicode escape sequences are malformed.\n   */\n  private char readEscapeCharacter() throws IOException {\n    if (!source.request(1)) {\n      throw syntaxError(\"Unterminated escape sequence\");\n    }\n\n    byte escaped = buffer.readByte();\n    switch (escaped) {\n      case 'u':\n        if (!source.request(4)) {\n          throw new EOFException(\"Unterminated escape sequence at path \" + getPath());\n        }\n        // Equivalent to Integer.parseInt(stringPool.get(buffer, pos, 4), 16);\n        char result = 0;\n        for (int i = 0, end = i + 4; i < end; i++) {\n          byte c = buffer.getByte(i);\n          result <<= 4;\n          if (c >= '0' && c <= '9') {\n            result += (c - '0');\n          } else if (c >= 'a' && c <= 'f') {\n            result += (c - 'a' + 10);\n          } else if (c >= 'A' && c <= 'F') {\n            result += (c - 'A' + 10);\n          } else {\n            throw syntaxError(\"\\\\u\" + buffer.readUtf8(4));\n          }\n        }\n        buffer.skip(4);\n        return result;","sourceCodeStart":978,"sourceCodeEnd":1014,"githubUrl":"https://github.com/airbnb/lottie-android/blob/05ea92e90381eb8a8ae06855ea2b74f322bebbec/lottie/src/main/java/com/airbnb/lottie/parser/moshi/JsonUtf8Reader.java#L978-L1014","documentation":"Thrown by readEscapeCharacter() when a `\\u` escape sequence is encountered but fewer than 4 hexadecimal digits follow before the input ends. JSON unicode escapes require exactly 4 hex digits (e.g., \\u0041 for 'A'). The check `source.request(4)` at line 995 fails when the stream doesn't have 4 more bytes, and an EOFException is thrown at line 996.","triggerScenarios":"A JSON string value contains a \\u escape that is truncated — e.g., \"\\u00\" (only 2 digits), \"\\u\" (no digits), or the input stream ends right after \\u. The readEscapeCharacter method at line 994 checks for the 'u' escape type, then at line 995 requests 4 bytes; if fewer are available, the throw at line 996 fires.","commonSituations":"A Lottie animation JSON with a text layer containing a malformed unicode escape (e.g., from a text expression that generated an invalid escape). A truncated JSON file cut off mid-escape. A file encoding or transfer issue that corrupted a multi-byte escape sequence. A minifier or compressor that incorrectly truncated unicode escapes.","solutions":["Search the JSON for \\u sequences and verify each has exactly 4 hexadecimal digits (0-9, A-F, a-f) following it","Re-export the animation from After Effects to regenerate valid escapes","If the file is truncated, re-download or re-export to ensure completeness","Pre-validate the JSON with a strict JSON parser (e.g., org.json.JSONObject) which will catch malformed escapes before Lottie attempts parsing"],"exampleFix":"// before: {\"t\": \"Hello\\u00 World}  // \\u00 has only 2 hex digits, and missing closing quote\n// after:  {\"t\": \"Hello\\u0041 World}  // \\u0041 = 'A', 4 valid hex digits","handlingStrategy":"validation","validationCode":"// Validate unicode escape sequences in the JSON\nboolean hasValidUnicodeEscapes(String json) {\n  java.util.regex.Pattern p = java.util.regex.Pattern.compile(\"\\\\\\\\u([0-9a-fA-F]{4})\");\n  java.util.regex.Pattern partial = java.util.regex.Pattern.compile(\"\\\\\\\\u(?![0-9a-fA-F]{4})\");\n  if (partial.matcher(json).find()) {\n    return false; // found a truncated \\u escape\n  }\n  return true;\n}\n\n// Usage:\nif (!hasValidUnicodeEscapes(jsonData)) {\n  Log.e(TAG, \"JSON contains malformed unicode escape\");\n  showFallback();\n}","typeGuard":null,"tryCatchPattern":"try {\n  LottieCompositionFactory.fromJsonData(jsonData, cacheKey);\n} catch (EOFException e) {\n  Log.w(TAG, \"Truncated escape sequence in Lottie JSON: \" + e.getMessage());\n  showFallbackAnimation();\n}","preventionTips":["Validate JSON with a standard parser before passing to Lottie — it will catch malformed escapes","Re-export animations from After Effects to regenerate valid unicode escapes","Check for file truncation if the JSON was downloaded or transferred"],"tags":["json-parsing","moshi","lottie","malformed-escape","unicode"],"backgroundTag":null,"analyzedSha":"05ea92e90381eb8a8ae06855ea2b74f322bebbec","analyzedAt":"2026-08-14T00:51:35.636Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}