airbnb/lottie-android · error · JsonEncodingException

JSON forbids NaN and infinities: {} at path {}

Error message

JSON forbids NaN and infinities: {} at path {}

What it means

Thrown by nextDouble() when the parsed double value is NaN or Infinity and the reader is in strict (non-lenient) mode. Per the JSON specification (RFC 8259), NaN and Infinity are not valid JSON number literals — they are unquoted identifiers that strict parsers reject. Moshi enforces this unless setLenient(true) was called.

Source

Thrown at lottie/src/main/java/com/airbnb/lottie/parser/moshi/JsonUtf8Reader.java:690

      peekedString = nextQuotedValue(DOUBLE_QUOTE_OR_SLASH);
    } else if (p == PEEKED_SINGLE_QUOTED) {
      peekedString = nextQuotedValue(SINGLE_QUOTE_OR_SLASH);
    } else if (p == PEEKED_UNQUOTED) {
      peekedString = nextUnquotedValue();
    } else if (p != PEEKED_BUFFERED) {
      throw new JsonDataException("Expected a double but was " + peek() + " at path " + getPath());
    }

    peeked = PEEKED_BUFFERED;
    double result;
    try {
      result = Double.parseDouble(peekedString);
    } catch (NumberFormatException e) {
      throw new JsonDataException("Expected a double but was " + peekedString
          + " at path " + getPath());
    }
    if (!lenient && (Double.isNaN(result) || Double.isInfinite(result))) {
      throw new JsonEncodingException("JSON forbids NaN and infinities: " + result
          + " at path " + getPath());
    }
    peekedString = null;
    peeked = PEEKED_NONE;
    pathIndices[stackSize - 1]++;
    return result;
  }

  /**
   * Returns the string up to but not including {@code quote}, unescaping any character escape
   * sequences encountered along the way. The opening quote should have already been read. This
   * consumes the closing quote, but does not include it in the returned string.
   *
   * @throws IOException if any unicode escape sequences are malformed.
   */
  private String nextQuotedValue(ByteString runTerminator) throws IOException {
    StringBuilder builder = null;
    while (true) {

View on GitHub (pinned to 05ea92e903)

Solutions

  1. Find the NaN/Infinity value in the JSON at the reported path and replace it with a valid finite number (e.g., 0.0 or the correct animation value)
  2. Re-export from After Effects ensuring no expression evaluates to NaN/Infinity
  3. If you control the JSON generation, sanitize: replace Double.isNaN/isInfinite values with 0.0 before serialization
  4. If you must accept these, set the reader to lenient mode — but note Lottie's internal parser controls this and strict mode is intentional

Example fix

// before: {"s": [{"x": Infinity, "y": NaN}]}
// after:  {"s": [{"x": 1.0, "y": 0.0}]}

// if generating JSON yourself, sanitize before serializing:
double safeVal = (Double.isNaN(val) || Double.isInfinite(val)) ? 0.0 : val;
Defensive patterns

Strategy: validation

Validate before calling

// Sanitize NaN/Infinity values before loading
String sanitizeJson(String json) {
  // Replace bare NaN and Infinity tokens with 0
  return json
    .replaceAll("(?<![\\w\"])\\bNaN\\b(?![\\w\"])", "0")
    .replaceAll("(?<![\\w\"])-?\\bInfinity\\b(?![\\w\"])", "0");
}

// Usage:
String cleanJson = sanitizeJson(rawJson);
LottieCompositionFactory.fromJsonData(cleanJson, cacheKey);

Try / catch

try {
  LottieCompositionFactory.fromJsonData(jsonData, cacheKey);
} catch (JsonEncodingException e) {
  // JSON forbids NaN and infinities
  Log.w(TAG, "Invalid numeric value in Lottie JSON: " + e.getMessage());
  // attempt to sanitize and retry, or fall back
  showFallbackAnimation();
}

Prevention

When it happens

Trigger: The JSON contains a bare NaN, Infinity, or -Infinity token where a double is expected, and the reader is not in lenient mode. This can also occur if a numeric literal overflows double range (e.g., 1e999) producing Infinity via Double.parseDouble. The check at JsonUtf8Reader.java:689 triggers the throw at line 690.

Common situations: A Lottie JSON file exported from a tool that serializes JavaScript's NaN/Infinity directly into the JSON. A corrupted animation property where a computed value became NaN during export. Hand-edited JSON that inserted Infinity as a placeholder. Older Bodymovin versions that didn't sanitize special float values.

Related errors


AI-assisted analysis of airbnb/lottie-android@05ea92e903 (2026-08-14). Data as JSON: /api/errors/acc01712efbcb946. Report an issue: GitHub.