{"record":{"id":"3703ead19c5a86d4","repo":"apache/hadoop","slug":"name-serial-number-map-is-full","errorCode":null,"errorMessage":"${name}: serial number map is full","messagePattern":"(.+?): serial number map is full","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SerialNumberMap.java","lineNumber":70,"sourceCode":"\n  SerialNumberMap(String name, int bitLength) {\n    this.name = name;\n    this.max = (1 << bitLength) - 1;\n  }\n\n  public int get(T t) {\n    if (t == null) {\n      return 0;\n    }\n    Integer sn = t2i.get(t);\n    if (sn == null) {\n      synchronized (this) {\n        sn = t2i.get(t);\n        if (sn == null) {\n          sn = current.getAndIncrement();\n          if (sn > max) {\n            current.getAndDecrement();\n            throw new IllegalStateException(name + \": serial number map is full\");\n          }\n          Integer old = t2i.putIfAbsent(t, sn);\n          if (old != null) {\n            current.getAndDecrement();\n            return old;\n          }\n          i2t.put(sn, t);\n        }\n      }\n    }\n    return sn;\n  }\n\n  public T get(int i) {\n    if (i == 0) {\n      return null;\n    }\n    T t = i2t.get(i);","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SerialNumberMap.java#L52-L88","documentation":"SerialNumberMap assigns each distinct value (user name, group name, xattr name) a serial starting at 1, bounded by max = 2^bitLength-1 where bitLength is the bit width of the field that stores the serial inside inodes/ACLs (USER/GROUP derive from PermissionStatusFormat and AclEntryStatusFormat.NAME; XATTR from XAttrFormat.NAME — roughly 65k entries; exact caps are logged at NN startup as '<NAME> serial map: bits=… maxEntries=…'). When a value not seen before would push the counter past max, the counter is rolled back and IllegalStateException '<name>: serial number map is full' is thrown. There is no eviction, so once full, any new distinct name of that kind fails.","triggerScenarios":"A namespace operation that introduces one more distinct user/group/xattr name than the map can hold — e.g., mkdir/setOwner/setPermission with a 65,536th unique owner, setAcl/setXattr with a new name — calls SerialNumberManager.getSerialNumber -> SerialNumberMap.get(T) and hits sn > max.","commonSituations":"Multi-tenant clusters with unbounded per-user directories created programmatically; a job or script that generates unique group names per run; xattr names generated with timestamps/UUIDs. Existing names keep working; only new distinct names fail, and the error can recur on every subsequent new-name edit.","solutions":["Check the NameNode startup log lines 'USER/GROUP/XATTR serial map: bits=… maxEntries=…' to learn the actual caps","Stop introducing new distinct names: reuse existing users/groups (centralize ownership mapping) and cap the xattr-name vocabulary","If already full, the practical remedy is a fresh-format-and-reload of the namespace (oiv -> recreate) so serials are re-allocated densely, done in a maintenance window","Track distinct counts proactively (audit logs / oiv -p XML analysis) and alert before reaching maxEntries"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// track distinct-name cardinality before you are near the cap\nSet<String> distinctOwners = new HashSet<>();\n// while generating ops:\nif (distinctOwners.size() >= SAFE_LIMIT /* e.g. 60000 */) {\n  owner = SHARED_SERVICE_USER; // reuse an existing identity\n} else {\n  distinctOwners.add(owner);\n}\n// then call hdfs.getClient().getProto().mkdir(..., owner, ...)","typeGuard":null,"tryCatchPattern":"try {\n  fs.setOwner(path, newUser, group);\n} catch (RemoteException re) {\n  if (re.getClassName().endsWith(\"IllegalStateException\")\n      && re.getMessage().contains(\"serial number map is full\")) {\n    // namespace hit the distinct user/group/xattr-name cap:\n    // stop generating new names, reuse existing identities\n  } else { throw re; }\n}","preventionTips":["Read the NN startup log lines 'USER/GROUP/XATTR serial map: bits=… maxEntries=…' to know your real caps","Never encode dynamic data (timestamps, UUIDs) into xattr names or owners; use a bounded vocabulary","Alert on distinct-user/group growth from audit logs and plan a re-load of the namespace well before the cap"],"tags":["hdfs","namenode","serial-number","capacity-exceeded","users-groups","xattr","illegal-state"],"backgroundTag":"capacity-exceeded","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}