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

Typed3EpoxyController finalizes `requestModelBuild()` and throws `IllegalStateException` unless `allowModelBuildRequests` is true, which happens only inside `setData(data1, data2, data3)`. The controller insists all rebuilds come with new data so its three typed data fields stay consistent with the built models.

Solutions

  1. Call `controller.setData(newData1, newData2, newData3)` with the current values for all three parameters.
  2. Store the latest data in the owning screen and re-submit it via `setData` whenever a rebuild is needed.
  3. If manual rebuild control is required, switch to base `EpoxyController` instead of a Typed variant.
  4. Make the subclass's `buildModels(data1, data2, data3)` a pure function of its arguments so re-submitting data is safe.

Example fix

// before
controller.requestModelBuild(); // IllegalStateException

// after
controller.setData(latestData1, latestData2, latestData3);
Defensive patterns

Strategy: validation

Validate before calling

// Typed3EpoxyController: refresh only via setData
controller.setData(newData1, newData2, newData3);

Prevention

When it happens

Trigger: Calling `controller.requestModelBuild()` directly from app code — e.g. after mutating one of the three data objects in place, or after a network callback completes, instead of calling `setData` again.

Common situations: Migrating from `EpoxyController` to a Typed3 controller while keeping old `requestModelBuild()` refresh calls; refreshing after a partial data update without re-supplying all three data objects; calling refresh from a presenter/viewmodel that holds stale data.

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


AI-assisted analysis of airbnb/epoxy@e45bd3a61f (2026-09-13). Data as JSON: /api/errors/370083a0b29d5f63. Report an issue: GitHub.

Appendix: source

Thrown at epoxy-adapter/src/main/java/com/airbnb/epoxy/Typed3EpoxyController.java:49

  }

  /**
   * 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)}
   */
  public void setData(T data1, U data2, V data3) {
    this.data1 = data1;
    this.data2 = data2;
    this.data3 = data3;
    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)