airbnb/epoxy · error · UnsupportedOperationException

Diffing is enabled. You should use notifyModelsChanged…

Error message

Diffing is enabled. You should use notifyModelsChanged instead of notifyDataSetChanged

What it means

When diffing is enabled, DiffHelper registers an AdapterDataObserver whose onChanged() throws UnsupportedOperationException. This catches calls to notifyDataSetChanged(), which would wipe RecyclerView's animation state and defeat the purpose of diffing. You must use notifyModelsChanged() instead, which runs the diff and emits granular notifications.

Solutions

  1. Replace notifyDataSetChanged() with notifyModelsChanged() on the EpoxyAdapter
  2. Remove or gate any framework/library code paths that call notifyDataSetChanged()
  3. Call notifyItemChanged/Inserted/Removed for single-item updates instead
  4. If blanket notification is truly needed, do not enable diffing on that adapter

Example fix

// before
adapter.notifyDataSetChanged();

// after
adapter.notifyModelsChanged();
Defensive patterns

Strategy: validation

Validate before calling

// avoid the throwing call when diffing is on
if (!adapter.isDiffingEnabled()) { adapter.notifyDataSetChanged(); } else { adapter.notifyModelsChanged(); }

Try / catch

// if third-party code may call it
try {
  adapter.notifyDataSetChanged();
} catch (UnsupportedOperationException e) {
  adapter.notifyModelsChanged();
}

Prevention

When it happens

Trigger: Calling adapter.notifyDataSetChanged() (directly or via RecyclerView helpers) on an EpoxyAdapter that has called enableDiffing().

Common situations: Copy-pasted RecyclerView code calling notifyDataSetChanged() after setModels(); Paging or SwipeRefresh callbacks that blanket-notify; upgrading from a non-diffing adapter to enableDiffing() without removing legacy notifyDataSetChanged calls.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at epoxy-adapter/src/main/java/com/airbnb/epoxy/DiffHelper.java:36

  // Using a HashMap instead of a LongSparseArray to
  // have faster look up times at the expense of memory
  private Map<Long, ModelState> oldStateMap = new HashMap<>();
  private ArrayList<ModelState> currentStateList = new ArrayList<>();
  private Map<Long, ModelState> currentStateMap = new HashMap<>();
  private final BaseEpoxyAdapter adapter;
  private final boolean immutableModels;


  DiffHelper(BaseEpoxyAdapter adapter, boolean immutableModels) {
    this.adapter = adapter;
    this.immutableModels = immutableModels;
    adapter.registerAdapterDataObserver(observer);
  }

  private final RecyclerView.AdapterDataObserver observer = new RecyclerView.AdapterDataObserver() {
    @Override
    public void onChanged() {
      throw new UnsupportedOperationException(
          "Diffing is enabled. You should use notifyModelsChanged instead of notifyDataSetChanged");
    }

    @Override
    public void onItemRangeChanged(int positionStart, int itemCount) {
      for (int i = positionStart; i < positionStart + itemCount; i++) {
        currentStateList.get(i).hashCode = adapter.getCurrentModels().get(i).hashCode();
      }
    }

    @Override
    public void onItemRangeInserted(int positionStart, int itemCount) {
      if (itemCount == 0) {
        // no-op
        return;
      }

      if (itemCount == 1 || positionStart == currentStateList.size()) {

View on GitHub (pinned to e45bd3a61f)