{"record":{"id":"cb3eb8e2709efe04","repo":"airbnb/epoxy","slug":"unknown-type-op-type","errorCode":null,"errorMessage":"Unknown type: {op.type}","messagePattern":"Unknown type: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"epoxy-adapter/src/main/java/com/airbnb/epoxy/DiffHelper.java","lineNumber":163,"sourceCode":"        case UpdateOp.ADD:\n          adapter.notifyItemRangeInserted(op.positionStart, op.itemCount);\n          break;\n        case UpdateOp.MOVE:\n          adapter.notifyItemMoved(op.positionStart, op.itemCount);\n          break;\n        case UpdateOp.REMOVE:\n          adapter.notifyItemRangeRemoved(op.positionStart, op.itemCount);\n          break;\n        case UpdateOp.UPDATE:\n          if (immutableModels && op.payloads != null) {\n            adapter.notifyItemRangeChanged(op.positionStart, op.itemCount,\n                new DiffPayload(op.payloads));\n          } else {\n            adapter.notifyItemRangeChanged(op.positionStart, op.itemCount);\n          }\n          break;\n        default:\n          throw new IllegalArgumentException(\"Unknown type: \" + op.type);\n      }\n    }\n  }\n\n  /**\n   * Create a list of operations that define the difference between {@link #oldStateList} and {@link\n   * #currentStateList}.\n   */\n  private UpdateOpHelper buildDiff(UpdateOpHelper updateOpHelper) {\n    prepareStateForDiff();\n\n    // The general approach is to first search for removals, then additions, and lastly changes.\n    // Focusing on one type of operation at a time makes it easy to coalesce batch changes.\n    // When we identify an operation and add it to the\n    // result list we update the positions of items in the oldStateList to reflect\n    // the change, this way subsequent operations will use the correct, updated positions.\n    collectRemovals(updateOpHelper);\n","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/airbnb/epoxy/blob/e45bd3a61fe3a1f130e184f5b8dcf172ab99025a/epoxy-adapter/src/main/java/com/airbnb/epoxy/DiffHelper.java#L145-L181","documentation":"notifyChanges() iterates diff-generated operations and switches on each op's type; a type outside the expected set falls into the default branch and throws IllegalArgumentException(\"Unknown type: ...\"). This is an internal invariant: the op list built by createOperationList should only contain known types, so hitting this indicates corrupted or externally-constructed operation data.","triggerScenarios":"Calling notifyModelChanges() when DiffHelper's internal operation list contains an unrecognized op type — effectively only possible with modified/interfered internal state, since ops are built internally from the diff.","commonSituations":"Custom forks of DiffHelper that added new op types without updating the switch; reflection-based tests constructing fake ops; a library version mismatch where a patched DiffHelper interacts with mismatched op constants.","solutions":["Use an unmodified stock version of DiffHelper/Epoxy (no forks)","Align library versions: ensure epoxy-adapter artifacts are all the same version","File a bug with a repro if it occurs on stock code — it is an internal invariant violation","Avoid constructing or mutating DiffOperation objects via reflection in tests"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  adapter.notifyModelsChanged();\n} catch (IllegalArgumentException e) {\n  if (e.getMessage() != null && e.getMessage().startsWith(\"Unknown type\")) {\n    Log.e(TAG, \"DiffHelper internal op error\", e);\n  } else { throw e; }\n}","preventionTips":["Use unmodified stock epoxy artifacts","Keep all epoxy module versions aligned","Do not construct diff operations via reflection"],"tags":["android","epoxy","diffing","internal"],"backgroundTag":"invalid-enum-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"}