apache/hadoop · error · IllegalArgumentException
Id {} exists but maps to {} and not {}
Error message
Id {} exists but maps to {} and not {} What it means
The mirror check in AbstractMapWritable.addToMap(clazz, id): if the byte id is already bound to a different class, IllegalArgumentException reports both the existing class and the attempted one. Together with the class->id check it guarantees the two maps stay bijective; violation means two classes claim the same wire id.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/AbstractMapWritable.java:79
byte getNewClasses() {
return newClasses;
}
/**
* Used to add "predefined" classes and by Writable to copy "new" classes.
*/
private synchronized void addToMap(Class<?> clazz, byte id) {
if (classToIdMap.containsKey(clazz)) {
byte b = classToIdMap.get(clazz);
if (b != id) {
throw new IllegalArgumentException ("Class " + clazz.getName() +
" already registered but maps to " + b + " and not " + id);
}
}
if (idToClassMap.containsKey(id)) {
Class<?> c = idToClassMap.get(id);
if (!c.equals(clazz)) {
throw new IllegalArgumentException("Id " + id + " exists but maps to " +
c.getName() + " and not " + clazz.getName());
}
}
classToIdMap.put(clazz, id);
idToClassMap.put(id, clazz);
}
/**
* Add a Class to the maps if it is not already present.
* @param clazz clazz.
*/
protected synchronized void addToMap(Class<?> clazz) {
if (classToIdMap.containsKey(clazz)) {
return;
}
if (newClasses + 1 > Byte.MAX_VALUE) {
throw new IndexOutOfBoundsException("adding an additional class would" +
" exceed the maximum number allowed");View on GitHub (pinned to 2add963021)
Solutions
- Pick custom fixed ids that do not collide with -127..-113 (the predefined range printed in the AbstractMapWritable constructor)
- Make registration order deterministic: static, fixed assignments rather than order-of-first-use
- Bump to a fresh set of ids (and drain queues) when changing registrations during upgrades
Defensive patterns
Strategy: try-catch
Validate before calling
// choose custom ids outside the predefined -127..-113 range and unique per class static final byte ID_TYPE_A = (byte) -100; // verify -100 is not already used
Try / catch
try {
map.readFields(in);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("exists but maps to")) {
// the byte id means a different class on the writer: version/registration mismatch
}
} Prevention
- Keep a central registry of class->id assignments in your codebase
- Test serialization round-trips between old and new versions during upgrades
- Avoid colliding with predefined ids -127..-113 bound by the base constructor
When it happens
Trigger: A custom registration picks an id that collides with a predefined one (AbstractMapWritable's constructor binds -127 through -113); deserializing a stream where the sender assigned that id to a different class because registration order differed; hand-written readFields mixing tables.
Common situations: Choosing custom ids like -120 without checking the predefined table; cluster nodes running builds where a new class was inserted in the middle of the registration list, shifting ids.
Related errors
- Class {} already registered but maps to {} and not {}
- adding an additional class would exceed the maximum number a
- map cannot be copied: {}
- source map cannot be null
- Exception while get content summary
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/64449a28ddbb7fc1.
Report an issue: GitHub.