airbnb/epoxy · error · IllegalStateException

You must enable diffing before modifying models

Error message

You must enable diffing before modifying models

What it means

enableDiffing() requires the adapter's model list to be empty at the time it is called; if models were already added it throws IllegalStateException. This guarantees the diff helper starts from a known baseline before any model mutations occur.

Solutions

  1. Move enableDiffing() to the first line of the adapter's constructor, before any addModel calls
  2. Clear models (removeAllModels) only if appropriate, then enable diffing — but prefer correct ordering
  3. Ensure no model population happens in superclass constructors before enableDiffing()

Example fix

// before
public MyAdapter() {
  addModels(new HeaderModel_());
  enableDiffing(); // throws
}

// after
public MyAdapter() {
  enableDiffing();
  addModels(new HeaderModel_());
}
Defensive patterns

Strategy: validation

Validate before calling

// enable diffing before any models are added
if (adapter.getItemCount() == 0) { enableDiffing(); } else { throw new IllegalStateException("Models must be empty before enableDiffing"); }

Prevention

When it happens

Trigger: Adding models via addModel(s)/add() before calling enableDiffing(), or calling enableDiffing() after the adapter has been populated.

Common situations: Calling enableDiffing() in onAttachedToRecyclerView or a setter instead of the constructor; populating models in the constructor before enabling diffing.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of airbnb/epoxy@e45bd3a61f (2026-09-13). Data as JSON: /api/errors/7abc6fdb5e8b46c2. Report an issue: GitHub.

Appendix: source

Thrown at epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyAdapter.java:48

  @Override
  List<EpoxyModel<?>> getCurrentModels() {
    return models;
  }

  /**
   * Enables support for automatically notifying model changes via {@link #notifyModelsChanged()}.
   * If used, this should be called in the constructor, before any models are changed.
   *
   * @see #notifyModelsChanged()
   */
  protected void enableDiffing() {
    if (diffHelper != null) {
      throw new IllegalStateException("Diffing was already enabled");
    }

    if (!models.isEmpty()) {
      throw new IllegalStateException("You must enable diffing before modifying models");
    }

    if (!hasStableIds()) {
      throw new IllegalStateException("You must have stable ids to use diffing");
    }

    diffHelper = new DiffHelper(this, false);
  }

  @Override
  EpoxyModel<?> getModelForPosition(int position) {
    EpoxyModel<?> model = models.get(position);
    return model.isShown() ? model : hiddenModel;
  }

  /**
   * Intelligently notify item changes by comparing the current {@link #models} list against the
   * previous so you don't have to micromanage notification calls yourself. This may be

View on GitHub (pinned to e45bd3a61f)