{"record":{"id":"c3a2eaa073a7eed4","repo":"apache/hadoop","slug":"adding-an-additional-class-would-exceed-the-maximu","errorCode":null,"errorMessage":"adding an additional class would exceed the maximum number allowed","messagePattern":"adding an additional class would exceed the maximum number allowed","errorType":"exception","errorClass":"IndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/AbstractMapWritable.java","lineNumber":96,"sourceCode":"      if (!c.equals(clazz)) {\n        throw new IllegalArgumentException(\"Id \" + id + \" exists but maps to \" +\n            c.getName() + \" and not \" + clazz.getName());\n      }\n    }\n    classToIdMap.put(clazz, id);\n    idToClassMap.put(id, clazz);\n  }\n  \n  /**\n   * Add a Class to the maps if it is not already present.\n   * @param clazz clazz.\n   */\n  protected synchronized void addToMap(Class<?> clazz) {\n    if (classToIdMap.containsKey(clazz)) {\n      return;\n    }\n    if (newClasses + 1 > Byte.MAX_VALUE) {\n      throw new IndexOutOfBoundsException(\"adding an additional class would\" +\n      \" exceed the maximum number allowed\");\n    }\n    byte id = ++newClasses;\n    addToMap(clazz, id);\n  }\n\n  /**\n   * the Class class for the specified id.\n   * @param id id.\n   * @return the Class class for the specified id.\n   */\n  protected Class<?> getClass(byte id) {\n    return idToClassMap.get(id);\n  }\n\n  /**\n   * get id.\n   * @return the id for the specified Class.","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/AbstractMapWritable.java#L78-L114","documentation":"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.","triggerScenarios":"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.","commonSituations":"Generic ETL code that boxes many domain types into a MapWritable; migrating maps of many types into Hadoop serialization without pre-registering.","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"],"exampleFix":"// before: each domain type eats one dynamic id -> cap at 127\nmap.put(new Text(\"user\"), new UserWritable(...));\nmap.put(new Text(\"order\"), new OrderWritable(...));\n\n// after: normalize values to Text, no per-type registration\nmap.put(new Text(\"user\"), new Text(jsonUser));\nmap.put(new Text(\"order\"), new Text(jsonOrder));","handlingStrategy":"validation","validationCode":"Set<Class<?>> distinct = map.keySet().stream()\n    .map(Object::getClass).collect(Collectors.toSet());\n// plus value types actually stored; if distinct types approach 127, normalize instead:\nif (distinct.size() > 100) {\n  throw new IllegalStateException(\"MapWritable nearing 127-class cap; encode values as Text\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  map.put(key, newValue);\n} catch (IndexOutOfBoundsException e) {\n  if (e.getMessage().contains(\"maximum number allowed\")) {\n    // no more dynamic ids: serialize values as Text/BytesWritable instead\n  }\n}","preventionTips":["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"],"tags":["hadoop","serialization","writable","mapwritable","limits"],"backgroundTag":"writable-registration-limit","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}