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

TypedEpoxyController disables direct requestModelBuild() calls after setup: models are rebuilt only when setData is called. Calling requestModelBuild() from outside the internal flow throws this IllegalStateException to enforce data-driven model building.

Solutions

  1. Call controller.setData(data) instead of requestModelBuild()
  2. If you need requestModelBuild semantics, use a plain EpoxyController or SimpleEpoxyController rather than a Typed one

Example fix

// before
controller.requestModelBuild();
// after
controller.setData(newData);
Defensive patterns

Strategy: validation

Validate before calling

if (controller is TypedEpoxyController<*>) controller.setData(data) else controller.requestModelBuild()

Type guard

fun isTypedController(c: EpoxyController) = c is TypedEpoxyController<*>

Prevention

When it happens

Trigger: Calling controller.requestModelBuild() on a TypedEpoxyController after construction, when allowModelBuildRequests has been set to false.

Common situations: Calling requestModelBuild from an Activity/Fragment after data changes instead of calling setData; copying EpoxyController usage patterns onto a TypedEpoxyController subclass.

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/bfaedf2d1ffc9832. Report an issue: GitHub.

Appendix: source

Thrown at epoxy-adapter/src/main/java/com/airbnb/epoxy/TypedEpoxyController.java:41

  public TypedEpoxyController() {
  }

  public TypedEpoxyController(Handler modelBuildingHandler, Handler diffingHandler) {
    super(modelBuildingHandler, diffingHandler);
  }

  public final void setData(T data) {
    currentData = data;
    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)