airbnb/epoxy · error · IllegalStateException
You cannot call `buildModels` directly. Call `setData`…
Error message
You cannot call `buildModels` directly. Call `setData` instead to trigger a model refresh with new data.
What it means
Typed3EpoxyController's `buildModels()` is final and forwards to the abstract `buildModels(data1, data2, data3)` only when `isBuildingModels()` is true, i.e. during a controller-initiated build pass. Direct calls throw `IllegalStateException` because models built outside the lifecycle won't be diffed/attached correctly.
Solutions
- Trigger building with `controller.setData(data1, data2, data3)`.
- In tests, submit data via `setData` or use Epoxy's testing helpers instead of calling the final `buildModels()`.
- Avoid calling `buildModels()` from constructors, other controllers, or background threads.
- Extract model construction into a pure helper function if you need the models independently of the controller lifecycle.
Example fix
// before controller.buildModels(data1, data2, data3); // IllegalStateException // after controller.setData(data1, data2, data3);
Defensive patterns
Strategy: validation
Validate before calling
// Wrong: controller.buildModels(data1, data2, data3); // Right: controller.setData(data1, data2, data3);
Prevention
- Treat buildModels overrides as framework-invoked only.
- Use setData (or Epoxy test helpers) in tests to produce models.
- Extract model construction into pure helpers if you need models outside the build pass.
When it happens
Trigger: Calling `controller.buildModels()` or the three-arg override directly from app code or tests instead of going through `setData(data1, data2, data3)`.
Common situations: Tests invoking `buildModels()` to inspect generated models; eager model building in a constructor/init; calling `buildModels()` after mutating data as a shortcut for `setData`.
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
- You cannot call `requestModelBuild` directly. Call…
- You cannot call `buildModels` directly. Call `setData`…
- You cannot call `requestModelBuild` directly. Call…
- You cannot call `requestModelBuild` directly. Call…
- Can only call this when inside the `buildModels` method
AI-assisted analysis of airbnb/epoxy@e45bd3a61f (2026-09-13).
Data as JSON: /api/errors/d3694743692dd9ac.
Report an issue: GitHub.
Appendix: source
Thrown at epoxy-adapter/src/main/java/com/airbnb/epoxy/Typed3EpoxyController.java:76
allowModelBuildRequests = true;
super.moveModel(fromPosition, toPosition);
allowModelBuildRequests = false;
}
@Override
public void requestDelayedModelBuild(int delayMs) {
if (!allowModelBuildRequests) {
throw new IllegalStateException(
"You cannot call `requestModelBuild` directly. Call `setData` instead to trigger a "
+ "model refresh with new data.");
}
super.requestDelayedModelBuild(delayMs);
}
@Override
protected final void buildModels() {
if (!isBuildingModels()) {
throw new IllegalStateException(
"You cannot call `buildModels` directly. Call `setData` instead to trigger a model "
+ "refresh with new data.");
}
buildModels(data1, data2, data3);
}
protected abstract void buildModels(T data1, U data2, V data3);
}
View on GitHub (pinned to e45bd3a61f)