airbnb/epoxy · error · IllegalArgumentException
Unknown type
Error message
Unknown type: {op.type} What it means
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.
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
Defensive patterns
Strategy: try-catch
Try / catch
try {
adapter.notifyModelsChanged();
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Unknown type")) {
Log.e(TAG, "DiffHelper internal op error", e);
} else { throw e; }
} Prevention
- Use unmodified stock epoxy artifacts
- Keep all epoxy module versions aligned
- Do not construct diff operations via reflection
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Diffing is enabled. You should use notifyModelsChanged…
- Moving more than 1 item at a time is not supported. Number…
- Two models have the same ID. ID's must be unique! Model at…
- Models must not be empty
- Diffing was already enabled
AI-assisted analysis of airbnb/epoxy@e45bd3a61f (2026-09-13).
Data as JSON: /api/errors/cb3eb8e2709efe04.
Report an issue: GitHub.
Appendix: source
Thrown at epoxy-adapter/src/main/java/com/airbnb/epoxy/DiffHelper.java:163
case UpdateOp.ADD:
adapter.notifyItemRangeInserted(op.positionStart, op.itemCount);
break;
case UpdateOp.MOVE:
adapter.notifyItemMoved(op.positionStart, op.itemCount);
break;
case UpdateOp.REMOVE:
adapter.notifyItemRangeRemoved(op.positionStart, op.itemCount);
break;
case UpdateOp.UPDATE:
if (immutableModels && op.payloads != null) {
adapter.notifyItemRangeChanged(op.positionStart, op.itemCount,
new DiffPayload(op.payloads));
} else {
adapter.notifyItemRangeChanged(op.positionStart, op.itemCount);
}
break;
default:
throw new IllegalArgumentException("Unknown type: " + op.type);
}
}
}
/**
* Create a list of operations that define the difference between {@link #oldStateList} and {@link
* #currentStateList}.
*/
private UpdateOpHelper buildDiff(UpdateOpHelper updateOpHelper) {
prepareStateForDiff();
// The general approach is to first search for removals, then additions, and lastly changes.
// Focusing on one type of operation at a time makes it easy to coalesce batch changes.
// When we identify an operation and add it to the
// result list we update the positions of items in the oldStateList to reflect
// the change, this way subsequent operations will use the correct, updated positions.
collectRemovals(updateOpHelper);
View on GitHub (pinned to e45bd3a61f)