{"record":{"id":"930035bb75c19264","repo":"apache/hadoop","slug":"layout-version-mismatch-this-oiv-tool-handles-la","errorCode":null,"errorMessage":"Layout version mismatch.  This oiv tool handles layout version {}, but the XML file has <layoutVersion> {}.  Please either re-generate the XML file with the proper layout version, or manually edit the XML file to be usable with this version of the oiv tool.","messagePattern":"Layout version mismatch\\.  This oiv tool handles layout version (.+?), but the XML file has <layoutVersion> (.+?)\\.  Please either re-generate the XML file with the proper layout version, or manually edit the XML file to be usable with this version of the oiv tool\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/offlineImageViewer/OfflineImageReconstructor.java","lineNumber":1702,"sourceCode":"      throw new IOException(\"No <version> section found at the top of \" +\n          \"the fsimage XML.  This XML file is too old to be processed \" +\n          \"by oiv.\", e);\n    }\n    Node version = new Node();\n    loadNodeChildren(version, \"version fields\");\n    Integer onDiskVersion = version.removeChildInt(\"onDiskVersion\");\n    if (onDiskVersion == null) {\n      throw new IOException(\"The <version> section doesn't contain \" +\n          \"the onDiskVersion.\");\n    }\n    Integer layoutVersion = version.removeChildInt(\"layoutVersion\");\n    if (layoutVersion == null) {\n      throw new IOException(\"The <version> section doesn't contain \" +\n          \"the layoutVersion.\");\n    }\n    if (layoutVersion.intValue() !=\n        NameNodeLayoutVersion.CURRENT_LAYOUT_VERSION) {\n      throw new IOException(\"Layout version mismatch.  This oiv tool \" +\n          \"handles layout version \" +\n          NameNodeLayoutVersion.CURRENT_LAYOUT_VERSION + \", but the \" +\n          \"XML file has <layoutVersion> \" + layoutVersion + \".  Please \" +\n          \"either re-generate the XML file with the proper layout version, \" +\n          \"or manually edit the XML file to be usable with this version \" +\n          \"of the oiv tool.\");\n    }\n    fileSummaryBld.setOndiskVersion(onDiskVersion);\n    fileSummaryBld.setLayoutVersion(layoutVersion);\n    if (LOG.isDebugEnabled()) {\n      LOG.debug(\"Loaded <version> with onDiskVersion=\" + onDiskVersion +\n          \", layoutVersion=\" + layoutVersion + \".\");\n    }\n  }\n\n  /**\n   * Write the string table to the fsimage.\n   * @throws IOException","sourceCodeStart":1684,"sourceCodeEnd":1720,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/offlineImageViewer/OfflineImageReconstructor.java#L1684-L1720","documentation":"The <version> block's <layoutVersion> does not equal NameNodeLayoutVersion.CURRENT_LAYOUT_VERSION of the oiv build doing the reconstruction. ReverseXML deliberately supports only the exact layout it was compiled for - one layout version means one on-disk protobuf schema - so cross-version reconstruction is rejected outright rather than producing a subtly corrupt image.","triggerScenarios":"Dumping XML with one Hadoop release's oiv and reconstructing with another (e.g. dump on 2.x, `hdfs oiv -processor ReverseXML` on 3.x), or hand-editing <layoutVersion> to a value the running oiv does not implement.","commonSituations":"Cluster upgrades between dump and restore; shared XML fixtures reused across Hadoop versions in CI; disaster recovery where the recovery host runs a different Hadoop release than the archived image.","solutions":["Regenerate the XML with the same Hadoop build you will reconstruct with (`hdfs oiv -processor XML`), then run ReverseXML in that same build","Alternatively run ReverseXML with the Hadoop version whose layout matches the XML, then roll the image forward via a NameNode layout upgrade","Check the error message: it names both the expected and actual layout versions - make them agree","Pin the Hadoop version in recovery runbooks so dump and reconstruct steps never drift"],"exampleFix":"# before: dump and reconstruct with different releases\nhdfs-oiv-2.8 -i fsimage_0001 -o dump.xml   # layoutVersion -60\nhdfs-oiv-3.3 -processor ReverseXML -i dump.xml -o fixed.img  # expects -66 -> fails\n# after: same release for both steps\nhdfs-oiv-3.3 -i fsimage_0001 -o dump.xml\nhdfs-oiv-3.3 -processor ReverseXML -i dump.xml -o fixed.img","handlingStrategy":"validation","validationCode":"# python: layoutVersion in the XML must equal the oiv build's current layout\nimport subprocess, xml.etree.ElementTree as ET\n\ndef layout_matches(path, current_lv):\n    for ev, el in ET.iterparse(path, events=('end',)):\n        if el.tag == 'layoutVersion':\n            return int(el.text) == current_lv\n    return False\n# obtain current_lv from the same Hadoop build, e.g.:\n#   hdfs oiv -processor XML -i fsimage_0001 -o probe.xml  (regenerate instead)","typeGuard":"def is_layout_compatible(xml_lv: int, oiv_current_lv: int) -> bool:\n    \"\"\"True only when the dump's layout equals the reconstructing oiv's layout.\"\"\"\n    return xml_lv == oiv_current_lv","tryCatchPattern":"# catch the mismatch message (it prints both versions); regenerate the XML\n# with the same Hadoop build, or switch the reconstructing oiv to that build","preventionTips":["Use one pinned Hadoop version for both dump and reconstruct steps","Record the Hadoop version alongside archived XML dumps","Run ReverseXML on the cluster's own Hadoop distribution","Never hand-edit <layoutVersion> to force compatibility"],"tags":["hdfs","oiv","fsimage","reversexml","layout-version","version-mismatch"],"backgroundTag":"fsimage-layout-version-mismatch","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}