{"record":{"id":"4bb922db29badf8e","repo":"apache/hadoop","slug":"string-table-bits-bits-maskbits","errorCode":null,"errorMessage":"String table bits ${bits} > ${maskBits}","messagePattern":"String table bits (.+?) > (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"critical","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SerialNumberManager.java","lineNumber":121,"sourceCode":"    int size = 0;\n    for (final SerialNumberManager snm : values) {\n      size += snm.size();\n    }\n    int tableMaskBits = getMaskBits();\n    StringTable map = new StringTable(size, tableMaskBits);\n    for (final SerialNumberManager snm : values) {\n      final int mask = snm.getMask(tableMaskBits);\n      for (Entry<Integer, String> entry : snm.entrySet()) {\n        map.put(entry.getKey() | mask, entry.getValue());\n      }\n    }\n    return map;\n  }\n\n  // returns an empty table for load.\n  public static StringTable newStringTable(int size, int bits) {\n    if (bits > maskBits) {\n      throw new IllegalArgumentException(\n        \"String table bits \" + bits + \" > \" + maskBits);\n    }\n    return new StringTable(size, bits);\n  }\n\n  public static class StringTable implements Iterable<Entry<Integer, String>> {\n    private final int tableMaskBits;\n    private final Map<Integer,String> map;\n\n    private StringTable(int size, int loadingMaskBits) {\n      this.tableMaskBits = loadingMaskBits;\n      this.map = new HashMap<>(size);\n    }\n\n    private String get(SerialNumberManager snm, int id) {\n      if (tableMaskBits != 0) {\n        if (id > maxEntryNumber) {\n          throw new IllegalStateException(","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SerialNumberManager.java#L103-L139","documentation":"SerialNumberManager packs name-to-serial tables (GLOBAL/USER/GROUP/XATTR) into the fsimage string table; the number of tables determines maskBits (this build: 4 tables -> maskBits=3, 29 entry bits). SerialNumberManager.newStringTable(size, bits) throws IllegalArgumentException when the string-table header read from an fsimage carries more mask bits than the running build supports — i.e., the image was written by a Hadoop version with more serial-number tables than this one can decode.","triggerScenarios":"Loading an fsimage (NameNode startup, 2NN checkpoint merge, offline image viewer) whose serialized string-table 'bits' field exceeds the reader's maskBits constant; happens exactly when a cluster is downgraded or read by older tooling after an image in the newer format was written.","commonSituations":"Rolling back to an older Hadoop release after a new-version checkpoint was saved; running 'hdfs oiv' from an older distribution against an image produced by a newer one; a standby/2NN on a different version than the active that wrote the image.","solutions":["Read or load the image with the same (or newer) Hadoop version that wrote it — check 'hdfs version' on both sides","If a downgrade is intended, perform it before any checkpoint in the new format exists, or bootstrap the node from a peer/backup that still has an old-format image","As a reader workaround, use the newer distribution's oiv/NN to convert the image, then proceed"],"exampleFix":"# before: older binary reading newer image\n$ /opt/hadoop-3.2/bin/hdfs oiv -i fsimage_0000000001000 -o dump.xml\njava.lang.IllegalArgumentException: String table bits 4 > 3\n# after: use the version that wrote the image\n$ /opt/hadoop-3.4/bin/hdfs oiv -i fsimage_0000000001000 -o dump.xml","handlingStrategy":"validation","validationCode":"// reject cross-version image loads up front\nint imageLayout = readImageLayoutVersion(new File(dir, \"current/VERSION\"));\nif (imageLayout < HdfsServerConstants.NAMENODE_LAYOUT_VERSION) {\n  throw new IOException(\"fsimage written by newer layout \" + imageLayout\n      + \"; this build supports \" + HdfsServerConstants.NAMENODE_LAYOUT_VERSION\n      + \" — upgrade this node before loading\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  SerialNumberManager.newStringTable(size, bits);\n} catch (IllegalArgumentException e) { // \"String table bits X > Y\"\n  throw new IOException(\"Image from a newer Hadoop build; \"\n      + \"load it with the version that wrote it\", e);\n}","preventionTips":["Never downgrade below the version that wrote the newest fsimage; check 'hdfs version' on all NNs/2NNs before rollback","Pin cluster-wide Hadoop versions and gate upgrades on image-format compatibility notes in the release","When sharing images across clusters, transfer the writer's version string alongside the file"],"tags":["hdfs","fsimage","serial-number","version-mismatch","downgrade","illegal-argument"],"backgroundTag":"version-mismatch","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}