airbnb/epoxy · error · IllegalStateException
You cannot call `requestModelBuild` directly. Call…
Error message
You cannot call `requestModelBuild` directly. Call `setData` instead to trigger a model refresh with new data.
What it means
Typed4EpoxyController finalizes `requestModelBuild()` and throws `IllegalStateException` unless `allowModelBuildRequests` is true, which is only the case transiently inside `setData(data1, data2, data3, data4)`. This enforces the Typed-controller contract: model rebuilds always accompany fresh data so all four data fields and the models stay in sync.
Solutions
- Call `controller.setData(newData1, newData2, newData3, newData4)` with all four current values.
- Keep the authoritative data in the owning screen and re-submit the full tuple on every change.
- Use base `EpoxyController` if manual rebuild control is genuinely needed.
- Make `buildModels(data1, data2, data3, data4)` depend only on its parameters so re-submission is idempotent.
Example fix
// before controller.requestModelBuild(); // IllegalStateException // after controller.setData(latestData1, latestData2, latestData3, latestData4);
Defensive patterns
Strategy: validation
Validate before calling
// Typed4EpoxyController: refresh only via setData controller.setData(newData1, newData2, newData3, newData4);
Prevention
- Always pass all four data values when refreshing a Typed4 controller.
- Keep an authoritative copy of the data tuple in the owning screen.
- Remove any requestModelBuild calls left over from migration.
When it happens
Trigger: Calling `controller.requestModelBuild()` directly, e.g. after mutating one of the four data objects in place or after an async update, instead of calling `setData` with new values.
Common situations: Porting refresh logic from plain `EpoxyController` to a Typed4 controller; pushing only some of the four data pieces and hoping a rebuild picks them up; triggering rebuilds from a presenter after network callbacks.
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 `buildModels` directly. Call `setData`…
- Can only call this when inside the `buildModels` method
AI-assisted analysis of airbnb/epoxy@e45bd3a61f (2026-09-13).
Data as JSON: /api/errors/5873361d5717053f.
Report an issue: GitHub.
Appendix: source
Thrown at epoxy-adapter/src/main/java/com/airbnb/epoxy/Typed4EpoxyController.java:51
/**
* Call this with the latest data when you want models to be rebuilt. The data will be passed on
* to {@link #buildModels(Object, Object, Object, Object)}
*/
public void setData(T data1, U data2, V data3, W data4) {
this.data1 = data1;
this.data2 = data2;
this.data3 = data3;
this.data4 = data4;
allowModelBuildRequests = true;
requestModelBuild();
allowModelBuildRequests = false;
}
@Override
public final void requestModelBuild() {
if (!allowModelBuildRequests) {
throw new IllegalStateException(
"You cannot call `requestModelBuild` directly. Call `setData` instead to trigger a "
+ "model refresh with new data.");
}
super.requestModelBuild();
}
@Override
public void moveModel(int fromPosition, int toPosition) {
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 "View on GitHub (pinned to e45bd3a61f)