google/ExoPlayer · error · IllegalArgumentException

Unknown RatingType: ${ratingType}

Error message

Unknown RatingType: ${ratingType}

What it means

Rating.CREATOR.fromBundle reads a rating-type discriminator int from the Bundle; if it is not one of the known constants (heart, percentage, star, thumb) — including UNSET — the static factory throws IllegalArgumentException. It means the Bundle was not produced by a Rating subclass's toBundle, or the persisted/tunneled data is corrupt or from an incompatible version.

Source

Thrown at library/common/src/main/java/com/google/android/exoplayer2/Rating.java:88

  /** Object that can restore a {@link Rating} from a {@link Bundle}. */
  public static final Creator<Rating> CREATOR = Rating::fromBundle;

  private static Rating fromBundle(Bundle bundle) {
    @RatingType
    int ratingType = bundle.getInt(FIELD_RATING_TYPE, /* defaultValue= */ RATING_TYPE_UNSET);
    switch (ratingType) {
      case RATING_TYPE_HEART:
        return HeartRating.CREATOR.fromBundle(bundle);
      case RATING_TYPE_PERCENTAGE:
        return PercentageRating.CREATOR.fromBundle(bundle);
      case RATING_TYPE_STAR:
        return StarRating.CREATOR.fromBundle(bundle);
      case RATING_TYPE_THUMB:
        return ThumbRating.CREATOR.fromBundle(bundle);
      case RATING_TYPE_UNSET:
      default:
        throw new IllegalArgumentException("Unknown RatingType: " + ratingType);
    }
  }
}

View on GitHub (pinned to dd430f7053)

Solutions

  1. Only pass Bundles created by HeartRating/PercentageRating/StarRating/ThumbRating.toBundle() into Rating.fromBundle.
  2. When reading untrusted Bundles, check the discriminator first: int t = bundle.getInt(FIELD_RATING_TYPE); verify it is 1-4 before calling fromBundle.
  3. If persisting ratings, store the typed object's fields yourself or round-trip through the same Media3 version.
  4. Align Media3 versions across processes (app vs. media session controller) to avoid unknown type constants.

Example fix

// before
Rating r = Rating.CREATOR.fromBundle(incomingBundle); // throws on unknown type

// after
int type = incomingBundle.getInt(Rating.FIELD_RATING_TYPE, Rating.RATING_TYPE_UNSET);
Rating r = (type == Rating.RATING_TYPE_HEART || type == Rating.RATING_TYPE_PERCENTAGE
    || type == Rating.RATING_TYPE_STAR || type == Rating.RATING_TYPE_THUMB)
        ? Rating.CREATOR.fromBundle(incomingBundle) : null;
Defensive patterns

Strategy: type-guard

Validate before calling

int t = bundle.getInt(Rating.FIELD_RATING_TYPE, Rating.RATING_TYPE_UNSET);
boolean known = t == Rating.RATING_TYPE_HEART || t == Rating.RATING_TYPE_PERCENTAGE
    || t == Rating.RATING_TYPE_STAR || t == Rating.RATING_TYPE_THUMB;

Type guard

static boolean isKnownRatingBundle(Bundle b) {
  int t = b.getInt(Rating.FIELD_RATING_TYPE, Rating.RATING_TYPE_UNSET);
  return t == Rating.RATING_TYPE_HEART || t == Rating.RATING_TYPE_PERCENTAGE
      || t == Rating.RATING_TYPE_STAR || t == Rating.RATING_TYPE_THUMB;
}

Try / catch

try { rating = Rating.CREATOR.fromBundle(b); } catch (IllegalArgumentException e) { rating = null; /* treat as unrated */ }

Prevention

When it happens

Trigger: Rating.fromBundle(bundle) where bundle.getInt(FIELD_RATING_TYPE) is missing or an unknown value. Occurs with hand-built Bundles, data restored from remote processes/backups written by a different Media3 version, or process-death state restoration of a malformed bundle.

Common situations: Passing a MediaMetadata or session rating Bundle across IPC from a non-Media3 producer; reading ratings from persistence where the int was never written; version skew where new rating types are read by an older library.

Related errors


AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14). Data as JSON: /api/errors/8e87caadb50108be. Report an issue: GitHub.