{"record":{"id":"d50f42d4be1b8d0f","repo":"airbnb/epoxy","slug":"controller-cannot-be-null","errorCode":null,"errorMessage":"Controller cannot be null","messagePattern":"Controller cannot be null","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyModel.java","lineNumber":414,"sourceCode":"   */\n  public void addIf(@NonNull AddPredicate predicate, @NonNull EpoxyController controller) {\n    addIf(predicate.addIf(), controller);\n  }\n\n  /**\n   * @see #addIf(AddPredicate, EpoxyController)\n   */\n  public interface AddPredicate {\n    boolean addIf();\n  }\n\n  /**\n   * This is used internally by generated models to turn on validation checking when\n   * \"validateEpoxyModelUsage\" is enabled and the model is used with an {@link EpoxyController}.\n   */\n  protected final void addWithDebugValidation(@NonNull EpoxyController controller) {\n    if (controller == null) {\n      throw new IllegalArgumentException(\"Controller cannot be null\");\n    }\n\n    if (controller.isModelAddedMultipleTimes(this)) {\n      throw new IllegalEpoxyUsage(\n          \"This model was already added to the controller at position \"\n              + controller.getFirstIndexOfModelInBuildingList(this));\n    }\n\n    if (firstControllerAddedTo == null) {\n      firstControllerAddedTo = controller;\n\n      // We save the current hashCode so we can compare it to the hashCode at later points in time\n      // in order to validate that it doesn't change and enforce mutability.\n      hashCodeWhenAdded = hashCode();\n\n      // The one time it is valid to change the model is during an interceptor callback. To support\n      // that we need to update the hashCode after interceptors have been run.\n      // The model can be added to multiple controllers, but we only allow an interceptor change","sourceCodeStart":396,"sourceCodeEnd":432,"githubUrl":"https://github.com/airbnb/epoxy/blob/e45bd3a61fe3a1f130e184f5b8dcf172ab99025a/epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyModel.java#L396-L432","documentation":"addWithDebugValidation is the internal hook generated models call when debug validation (validateEpoxyModelUsage) is enabled. It requires the owning EpoxyController; a null controller means the model's usage cannot be validated, so Epoxy throws IllegalArgumentException immediately.","triggerScenarios":"A generated model's addWithDebugValidation(controller) is invoked with a null controller argument, typically when the model's controller reference was never set or was passed as null from generated code.","commonSituations":"Manually invoking internal API; generated model used outside a controller's buildModels scope while validation is enabled; a controller field not yet assigned when the model is added.","solutions":["Always add models inside a controller's buildModels method so a valid controller is provided","Ensure the controller reference passed to the model is non-null before adding","Disable validateEpoxyModelUsage only if you truly use models without a controller"],"exampleFix":"// before\nmodel.addWithDebugValidation(null);\n// after\n@Override public void buildModels(List<EpoxyModel<?>> models) { model.addWithDebugValidation(this); }","handlingStrategy":"type-guard","validationCode":"if (controller == null) { throw new IllegalStateException(\"Controller must be assigned before adding models\"); }","typeGuard":"if (!(model instanceof GeneratedModel<?> g) || g.controller() == null) { skipAdd(); }","tryCatchPattern":"try { model.addTo(controller); } catch (IllegalArgumentException e) { Log.e(TAG, \"Model added without controller\", e); }","preventionTips":["Always add models inside buildModels","Initialize controller fields before model setup"],"tags":["android","epoxy","null-check","validation"],"backgroundTag":"null-argument","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"}