airbnb/epoxy · error · IllegalEpoxyUsage
You cannot call `requestModelBuild` directly. Call…
Error message
You cannot call `requestModelBuild` directly. Call `setModels` instead.
What it means
SimpleEpoxyController.final requestModelBuild throws IllegalEpoxyUsage unless called from inside setModels, because with SimpleEpoxyController models are derived from a plain data list — building is triggered automatically by setModels, and a direct requestModelBuild would bypass that contract.
Solutions
- Replace requestModelBuild() with controller.setModels(yourList) when using SimpleEpoxyController
- Call setModels whenever the underlying data changes; the controller rebuilds automatically
- If manual rebuilds are needed, switch to a custom EpoxyController with buildModels()
Example fix
// before controller.requestModelBuild(); // after controller.setModels(data);
Defensive patterns
Strategy: validation
Validate before calling
if (controller instanceof SimpleEpoxyController) {
controller.setModels(data); // not requestModelBuild()
} Type guard
boolean supportsDirectRebuild(EpoxyController c) { return !(c instanceof SimpleEpoxyController); } Try / catch
try { controller.requestModelBuild(); } catch (IllegalEpoxyUsage e) { controller.setModels(currentData); } Prevention
- With SimpleEpoxyController always call setModels on data change
- Reserve requestModelBuild for custom EpoxyControllers
- Document the rebuild API of each controller type in your team
- Base-class-check before calling lifecycle methods in shared code
When it happens
Trigger: Calling controller.requestModelBuild() directly from app code on a SimpleEpoxyController (outside setModels, where insideSetModels is false).
Common situations: Copy-pasting controller code: requestModelBuild is correct for custom EpoxyControllers but illegal for SimpleEpoxyController; reacting to data changes by manually rebuilding instead of calling setModels.
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
- Models cannot be changed once they are added to the…
- Must have stable ids when saving view holder state
- State cannot be restored once views have been bound. It…
- Tried to restore instance state, but onSaveInstanceState…
- numItemsToPrefetch must be greater than 0
AI-assisted analysis of airbnb/epoxy@e45bd3a61f (2026-09-13).
Data as JSON: /api/errors/9ed070eeaf72e20b.
Report an issue: GitHub.
Appendix: source
Thrown at epoxy-adapter/src/main/java/com/airbnb/epoxy/SimpleEpoxyController.java:27
public class SimpleEpoxyController extends EpoxyController {
private List<? extends EpoxyModel<?>> currentModels;
private boolean insideSetModels;
/**
* Set the models to add to this controller. Clears any previous models and adds this new list
* .
*/
public void setModels(List<? extends EpoxyModel<?>> models) {
currentModels = models;
insideSetModels = true;
requestModelBuild();
insideSetModels = false;
}
@Override
public final void requestModelBuild() {
if (!insideSetModels) {
throw new IllegalEpoxyUsage(
"You cannot call `requestModelBuild` directly. Call `setModels` instead.");
}
super.requestModelBuild();
}
@Override
protected final void buildModels() {
if (!isBuildingModels()) {
throw new IllegalEpoxyUsage(
"You cannot call `buildModels` directly. Call `setModels` instead.");
}
add(currentModels);
}
}
View on GitHub (pinned to e45bd3a61f)