{"record":{"id":"242ef9d452b39d2d","repo":"airbnb/epoxy","slug":"a-model-was-selected-that-is-not-a-valid-target","errorCode":null,"errorMessage":"A model was selected that is not a valid target: ","messagePattern":"A model was selected that is not a valid target: ","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyModelTouchCallback.java","lineNumber":122,"sourceCode":"    }\n\n    //noinspection unchecked\n    onSwipeCompleted((T) model, view, position, direction);\n  }\n\n  @Override\n  public void onSwipeCompleted(T model, View itemView, int position, int direction) {\n\n  }\n\n  @Override\n  protected void onSelectedChanged(@Nullable EpoxyViewHolder viewHolder, int actionState) {\n    super.onSelectedChanged(viewHolder, actionState);\n\n    if (viewHolder != null) {\n      EpoxyModel<?> model = viewHolder.getModel();\n      if (!isTouchableModel(model)) {\n        throw new IllegalStateException(\n            \"A model was selected that is not a valid target: \" + model.getClass());\n      }\n\n      markRecyclerViewHasSelection((RecyclerView) viewHolder.itemView.getParent());\n\n      if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {\n        holderBeingSwiped = viewHolder;\n        //noinspection unchecked\n        onSwipeStarted((T) model, viewHolder.itemView, viewHolder.getAdapterPosition());\n      } else if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {\n        holderBeingDragged = viewHolder;\n        //noinspection unchecked\n        onDragStarted((T) model, viewHolder.itemView, viewHolder.getAdapterPosition());\n      }\n    } else if (holderBeingDragged != null) {\n      //noinspection unchecked\n      onDragReleased((T) holderBeingDragged.getModel(), holderBeingDragged.itemView);\n      holderBeingDragged = null;","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/airbnb/epoxy/blob/e45bd3a61fe3a1f130e184f5b8dcf172ab99025a/epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyModelTouchCallback.java#L104-L140","documentation":"Epoxy throws this IllegalStateException from ItemTouchHelper's onSelectedChanged callback when a ViewHolder begins a drag or swipe but its model is not registered as touchable. EpoxyModelTouchCallback only permits models explicitly allowed by isTouchableModel, so an unregistered model being touched indicates a misconfiguration between the adapter's models and the touch callback.","triggerScenarios":"A swipe/drag starts on a view holder whose model is not in the set of touchable models (e.g. the model list contains a model type not handled by isTouchableModel, or touchable model registration was changed/omitted).","commonSituations":"Adding new model types to a RecyclerView with swipe-to-dismiss or drag-and-drop without updating the touch callback's allowed models; mixing generic EpoxyModel instances into a list intended only for touchable models.","solutions":["Override isTouchableModel in your EpoxyModelTouchCallback subclass to return true for the model class being selected","Ensure the touch callback is attached to a controller/adapter whose models all pass isTouchableModel","Check that the model class being swiped/dragged matches the class registered in the callback (subclass/generics mismatch)"],"exampleFix":"// before\n@Override\nprotected boolean isTouchableModel(EpoxyModel<?> model) {\n  return model instanceof SwipeOutModel;\n}\n// after\n@Override\nprotected boolean isTouchableModel(EpoxyModel<?> model) {\n  return model instanceof SwipeOutModel || model instanceof DraggableModel;\n}","handlingStrategy":"validation","validationCode":"if (callback.isTouchableModel(model)) {\n  itemTouchHelper.attachToRecyclerView(recyclerView);\n}","typeGuard":"boolean isTouchable(EpoxyModel<?> m) { return m instanceof SwipeOutModel || m instanceof DraggableModel; }","tryCatchPattern":"try { touchHelper.onSwiped(vh, dir); } catch (IllegalStateException e) { Log.w(TAG, \"non-touchable model selected\", e); }","preventionTips":["Update isTouchableModel whenever adding a new model type to the list","Only attach ItemTouchHelper to lists of touchable models","Avoid swapping model data mid-gesture"],"tags":["android","epoxy","item-touch-helper","touch-callback"],"backgroundTag":"invalid-argument-value","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"}