airbnb/epoxy · error · IllegalArgumentException
Models cannot be empty
Error message
Models cannot be empty
What it means
An EpoxyModelGroup wraps a set of models and binds them into one layout; with zero models there is nothing to bind and no id to inherit (it takes the id of the first model), so the private constructor throws IllegalArgumentException for an empty list.
Solutions
- Check that the list is non-empty before constructing the group, or skip adding the group entirely
- Add a placeholder/empty-state model instead of an empty group
- Guard builder code paths that construct groups from dynamic data
Example fix
// before
add(new EpoxyModelGroup_(R.layout.group).models(subList)); // throws when empty
// after
if (!subList.isEmpty()) { add(new EpoxyModelGroup_(R.layout.group).models(subList)); } Defensive patterns
Strategy: validation
Validate before calling
if (models == null || models.isEmpty()) { return; } // skip group Type guard
if (!(models instanceof List) || ((List<?>) models).isEmpty()) return;
Try / catch
try { add(new EpoxyModelGroup_(layout).models(models)); } catch (IllegalArgumentException e) { Log.w(TAG, "Empty group skipped"); } Prevention
- Check list size before grouping
- Render an empty-state model instead of an empty group
When it happens
Trigger: Constructing an EpoxyModelGroup (or using withModels builders that delegate to it) with an empty List<EpoxyModel<?>>.
Common situations: Building groups from filtered/empty data lists without checking size; grouping sub-lists where a page may return zero items.
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
- You must set an id on a model before adding it. Use the…
- Controller cannot be null
- This model was already added to the controller at position
- Epoxy attribute fields on a model cannot be changed once…
- Must have stable ids when saving view holder state
AI-assisted analysis of airbnb/epoxy@e45bd3a61f (2026-09-13).
Data as JSON: /api/errors/d49daeda4e9843c6.
Report an issue: GitHub.
Appendix: source
Thrown at epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyModelGroup.java:93
public EpoxyModelGroup(@LayoutRes int layoutRes, Collection<? extends EpoxyModel<?>> models) {
this(layoutRes, new ArrayList<>(models));
}
/**
* @param layoutRes The layout to use with these models.
* @param models The models that will be used to bind the views in the given layout.
*/
public EpoxyModelGroup(@LayoutRes int layoutRes, EpoxyModel<?>... models) {
this(layoutRes, new ArrayList<>(Arrays.asList(models)));
}
/**
* @param layoutRes The layout to use with these models.
* @param models The models that will be used to bind the views in the given layout.
*/
private EpoxyModelGroup(@LayoutRes int layoutRes, List<EpoxyModel<?>> models) {
if (models.isEmpty()) {
throw new IllegalArgumentException("Models cannot be empty");
}
this.models = models;
layout(layoutRes);
id(models.get(0).id());
boolean saveState = false;
for (EpoxyModel<?> model : models) {
if (model.shouldSaveViewState()) {
saveState = true;
break;
}
}
// By default we save view state if any of the models need to save state.
shouldSaveViewStateDefault = saveState;
}
/**View on GitHub (pinned to e45bd3a61f)