airbnb/epoxy · error · IllegalStateException
Models must not be empty
Error message
Models must not be empty
What it means
DiffPayload's package-private constructor requires a non-empty list of changed models; an empty list throws IllegalStateException. Payloads describe the old versions of models for a change notification, so an empty list means nothing changed and no payload should be created.
Solutions
- Skip creating a payload when the changed-models list is empty (emit plain notifyItemRangeChanged instead)
- Use stock epoxy versions rather than forks that may pass empty lists
- In tests, never build DiffPayload with an empty list; assert models before constructing
Example fix
// before
new DiffPayload(Collections.emptyList()); // throws
// after
if (!models.isEmpty()) {
new DiffPayload(models);
} Defensive patterns
Strategy: validation
Validate before calling
// only create a payload when there is at least one model if (models.isEmpty()) return; new DiffPayload(models);
Prevention
- Skip payload creation for empty change sets
- Prefer stock DiffHelper, which never passes empty lists
- In tests, guard DiffPayload construction with an isEmpty check
When it happens
Trigger: Constructing DiffPayload with an empty List<EpoxyModel<?>> — only reachable via onItemRangeChanged in DiffHelper passing a payload list with no models, or via direct construction in the same package/tests.
Common situations: Modified/forked DiffHelper code that adds empty payload lists for change notifications; test code building DiffPayload directly; library-internal edge cases on stock code are not expected to hit this.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- 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…
- Diffing was already enabled
AI-assisted analysis of airbnb/epoxy@e45bd3a61f (2026-09-13).
Data as JSON: /api/errors/cca59f9cdf519af4.
Report an issue: GitHub.
Appendix: source
Thrown at epoxy-adapter/src/main/java/com/airbnb/epoxy/DiffPayload.java:22
import java.util.List;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.collection.LongSparseArray;
/**
* A helper class for tracking changed models found by the {@link com.airbnb.epoxy.DiffHelper} to
* be included as a payload in the
* {@link androidx.recyclerview.widget.RecyclerView.Adapter#notifyItemChanged(int, Object)}
* call.
*/
public class DiffPayload {
private final EpoxyModel<?> singleModel;
private final LongSparseArray<EpoxyModel<?>> modelsById;
DiffPayload(List<? extends EpoxyModel<?>> models) {
if (models.isEmpty()) {
throw new IllegalStateException("Models must not be empty");
}
int modelCount = models.size();
if (modelCount == 1) {
// Optimize for the common case of only one model changed.
singleModel = models.get(0);
modelsById = null;
} else {
singleModel = null;
modelsById = new LongSparseArray<>(modelCount);
for (EpoxyModel<?> model : models) {
modelsById.put(model.id(), model);
}
}
}
public DiffPayload(EpoxyModel<?> changedItem) {View on GitHub (pinned to e45bd3a61f)