{"record":{"id":"7def93f572576896","repo":"airbnb/epoxy","slug":"moving-more-than-1-item-at-a-time-is-not-supported-number-of","errorCode":null,"errorMessage":"Moving more than 1 item at a time is not supported. Number of items moved: {itemCount}","messagePattern":"Moving more than 1 item at a time is not supported\\. Number of items moved: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"epoxy-adapter/src/main/java/com/airbnb/epoxy/DiffHelper.java","lineNumber":104,"sourceCode":"      }\n      modelsToRemove.clear();\n\n      // Update positions of affected items\n      int size = currentStateList.size();\n      for (int i = positionStart; i < size; i++) {\n        currentStateList.get(i).position -= itemCount;\n      }\n    }\n\n    @Override\n    public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {\n      if (fromPosition == toPosition) {\n        // no-op\n        return;\n      }\n\n      if (itemCount != 1) {\n        throw new IllegalArgumentException(\"Moving more than 1 item at a time is not \"\n            + \"supported. Number of items moved: \" + itemCount);\n      }\n\n      ModelState model = currentStateList.remove(fromPosition);\n      model.position = toPosition;\n      currentStateList.add(toPosition, model);\n\n      if (fromPosition < toPosition) {\n        // shift the affected items left\n        for (int i = fromPosition; i < toPosition; i++) {\n          currentStateList.get(i).position--;\n        }\n      } else {\n        // shift the affected items right\n        for (int i = toPosition + 1; i <= fromPosition; i++) {\n          currentStateList.get(i).position++;\n        }\n      }","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/airbnb/epoxy/blob/e45bd3a61fe3a1f130e184f5b8dcf172ab99025a/epoxy-adapter/src/main/java/com/airbnb/epoxy/DiffHelper.java#L86-L122","documentation":"DiffHelper's move handling only supports single-item moves; when onItemRangeMoved receives itemCount != 1 it throws IllegalArgumentException. Multi-item moves cannot be applied to the internal ModelState list with the simple remove/re-add logic used here.","triggerScenarios":"A move notification with more than one item (notifyItemRangeMoved with itemCount > 1, or AdapterListUpdateCallback batching a multi-element drag move) reaches the DiffHelper observer.","commonSituations":"Drag-and-drop reordering libraries (e.g. ItemTouchHelper with multi-selection) that move several items and coalesce them into one range-move notification; custom adapters emitting range moves.","solutions":["Emit one notifyItemMoved(from, to) per moved item instead of a range move","Perform multi-item reorders via notifyModelsChanged() so the diff computes them","Reorder the model list yourself and let the diff detect the changes","Split the move into a remove+insert pair if single-move emission is impossible"],"exampleFix":"// before\nadapter.notifyItemRangeMoved(from, to, 3); // throws in DiffHelper\n\n// after\nfor (int i = 0; i < 3; i++) {\n  adapter.notifyItemMoved(from + i, to + i);\n}","handlingStrategy":"validation","validationCode":"// emit single-item moves only\nif (itemCount == 1) { adapter.notifyItemMoved(fromPosition, toPosition); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never call notifyItemRangeMoved with itemCount > 1 on diffing adapters","In ItemTouchHelper onMove, call notifyItemMoved per drag step","For batch reorders, mutate the model list and call notifyModelsChanged()"],"tags":["android","epoxy","diffing","recyclerview"],"backgroundTag":"unsupported-operation","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"}