{"record":{"id":"bfaedf2d1ffc9832","repo":"airbnb/epoxy","slug":"you-cannot-call-requestmodelbuild-directly-call-setdata-bfaedf","errorCode":null,"errorMessage":"You cannot call `requestModelBuild` directly. Call `setData` instead to trigger a model refresh with new data.","messagePattern":"You cannot call `requestModelBuild` directly\\. Call `setData` instead to trigger a model refresh with new data\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"epoxy-adapter/src/main/java/com/airbnb/epoxy/TypedEpoxyController.java","lineNumber":41,"sourceCode":"\n  public TypedEpoxyController() {\n  }\n\n  public TypedEpoxyController(Handler modelBuildingHandler, Handler diffingHandler) {\n    super(modelBuildingHandler, diffingHandler);\n  }\n\n  public final void setData(T data) {\n    currentData = data;\n    allowModelBuildRequests = true;\n    requestModelBuild();\n    allowModelBuildRequests = false;\n  }\n\n  @Override\n  public final void requestModelBuild() {\n    if (!allowModelBuildRequests) {\n      throw new IllegalStateException(\n          \"You cannot call `requestModelBuild` directly. Call `setData` instead to trigger a \"\n              + \"model refresh with new data.\");\n    }\n    super.requestModelBuild();\n  }\n\n  @Override\n  public void moveModel(int fromPosition, int toPosition) {\n    allowModelBuildRequests = true;\n    super.moveModel(fromPosition, toPosition);\n    allowModelBuildRequests = false;\n  }\n\n  @Override\n  public void requestDelayedModelBuild(int delayMs) {\n    if (!allowModelBuildRequests) {\n      throw new IllegalStateException(\n          \"You cannot call `requestModelBuild` directly. Call `setData` instead to trigger a \"","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/airbnb/epoxy/blob/e45bd3a61fe3a1f130e184f5b8dcf172ab99025a/epoxy-adapter/src/main/java/com/airbnb/epoxy/TypedEpoxyController.java#L23-L59","documentation":"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.","triggerScenarios":"Calling controller.requestModelBuild() on a TypedEpoxyController after construction, when allowModelBuildRequests has been set to false.","commonSituations":"Calling requestModelBuild from an Activity/Fragment after data changes instead of calling setData; copying EpoxyController usage patterns onto a TypedEpoxyController subclass.","solutions":["Call controller.setData(data) instead of requestModelBuild()","If you need requestModelBuild semantics, use a plain EpoxyController or SimpleEpoxyController rather than a Typed one"],"exampleFix":"// before\ncontroller.requestModelBuild();\n// after\ncontroller.setData(newData);","handlingStrategy":"validation","validationCode":"if (controller is TypedEpoxyController<*>) controller.setData(data) else controller.requestModelBuild()","typeGuard":"fun isTypedController(c: EpoxyController) = c is TypedEpoxyController<*>","tryCatchPattern":null,"preventionTips":["Route all refresh calls through setData for typed controllers","Document that TypedEpoxyController is data-driven only","Add lint/arch checks banning requestModelBuild on typed controllers"],"tags":["android","epoxy","illegal-state","api-misuse"],"backgroundTag":"invalid-state-transition","analyzedSha":"e45bd3a61fe3a1f130e184f5b8dcf172ab99025a","analyzedAt":"2026-09-13T03:24:16.052Z","contentChangedAt":"2026-09-13T03:24:16.052Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}