apache/hadoop · error · IndexOutOfBoundsException
adding an additional class would exceed the maximum number a
Error message
adding an additional class would exceed the maximum number allowed
What it means
Dynamically registered classes (those not pre-assigned a fixed id) get consecutive positive byte ids via ++newClasses. Once the count would exceed Byte.MAX_VALUE (127), addToMap(clazz) throws IndexOutOfBoundsException - the wire format only has one byte for the id, so a MapWritable cannot carry more than 127 distinct dynamic types.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/AbstractMapWritable.java:96
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");
}
byte id = ++newClasses;
addToMap(clazz, id);
}
/**
* the Class class for the specified id.
* @param id id.
* @return the Class class for the specified id.
*/
protected Class<?> getClass(byte id) {
return idToClassMap.get(id);
}
/**
* get id.
* @return the id for the specified Class.View on GitHub (pinned to 2add963021)
Solutions
- Reduce distinct value types: encode values as Text/BytesWritable instead of one Writable class per type
- Pre-register your types with fixed negative ids (outside -127..-113) if you control the subclass, since predefined ids do not count against the 127
- Switch containers: ObjectWritable, a custom Writable with an explicit type tag, or a serialization framework without the byte-id cap
Example fix
// before: each domain type eats one dynamic id -> cap at 127
map.put(new Text("user"), new UserWritable(...));
map.put(new Text("order"), new OrderWritable(...));
// after: normalize values to Text, no per-type registration
map.put(new Text("user"), new Text(jsonUser));
map.put(new Text("order"), new Text(jsonOrder)); Defensive patterns
Strategy: validation
Validate before calling
Set<Class<?>> distinct = map.keySet().stream()
.map(Object::getClass).collect(Collectors.toSet());
// plus value types actually stored; if distinct types approach 127, normalize instead:
if (distinct.size() > 100) {
throw new IllegalStateException("MapWritable nearing 127-class cap; encode values as Text");
} Try / catch
try {
map.put(key, newValue);
} catch (IndexOutOfBoundsException e) {
if (e.getMessage().contains("maximum number allowed")) {
// no more dynamic ids: serialize values as Text/BytesWritable instead
}
} Prevention
- Limit MapWritable to a small, known set of Writable types
- Pre-register frequent types with fixed negative ids so they do not consume dynamic ids
- For rich schemas use Avro/Proto or a custom Writable rather than MapWritable
When it happens
Trigger: Using MapWritable/SortedMapWritable as a heterogeneous bag and putting values of more than 127 distinct Writable classes into one instance (each new class consumes one id); long-lived accumulators that keep adding new value types.
Common situations: Generic ETL code that boxes many domain types into a MapWritable; migrating maps of many types into Hadoop serialization without pre-registering.
Related errors
- Class {} already registered but maps to {} and not {}
- Id {} exists but maps to {} and not {}
- 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/c3a2eaa073a7eed4.
Report an issue: GitHub.