airbnb/epoxy · error · IllegalStateException
Diffing was already enabled
Error message
Diffing was already enabled
What it means
EpoxyAdapter.enableDiffing() throws IllegalStateException if diffHelper is already non-null, meaning enableDiffing() was called twice. The helper registers an observer; double registration would duplicate diff work and notifications, so it is disallowed.
Solutions
- Call enableDiffing() exactly once, in the adapter's constructor
- If unsure, guard the call: only call when diffHelper is not yet enabled (use a subclass flag if diffHelper is inaccessible)
- Remove duplicate calls in subclass constructors where the superclass already enables diffing
Example fix
// before
public MyAdapter() {
super();
enableDiffing(); // super already called it
}
// after
public MyAdapter() {
super(); // superclass constructor calls enableDiffing() once
} Defensive patterns
Strategy: validation
Validate before calling
// enable diffing only once
if (!diffingEnabled) { enableDiffing(); diffingEnabled = true; } Prevention
- Call enableDiffing() exactly once, in the constructor
- Don't re-enable in subclasses if the superclass already does
- Keep adapter configuration in one place
When it happens
Trigger: Calling enableDiffing() more than once on the same adapter instance — e.g. in a constructor that a subclass also calls, or re-invoking it after reconfiguration.
Common situations: Base-class constructor calls enableDiffing() and a subclass constructor calls it again; developer adds the call defensively in an init path that runs repeatedly (adapter reuse/rebind).
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
- You must enable diffing before modifying models
- Diffing is enabled. You should use notifyModelsChanged…
- Moving more than 1 item at a time is not supported. Number…
- Unknown type
- Two models have the same ID. ID's must be unique! Model at…
AI-assisted analysis of airbnb/epoxy@e45bd3a61f (2026-09-13).
Data as JSON: /api/errors/d126ba3828bd9c32.
Report an issue: GitHub.
Appendix: source
Thrown at epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyAdapter.java:44
* are responsible for notifying data changes whenever this list is changed.
*/
protected final List<EpoxyModel<?>> models = new ModelList();
private DiffHelper diffHelper;
@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;
}View on GitHub (pinned to e45bd3a61f)