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

  1. Replace requestModelBuild() with controller.setModels(yourList) when using SimpleEpoxyController
  2. Call setModels whenever the underlying data changes; the controller rebuilds automatically
  3. 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

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


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)