{"record":{"id":"75110344c046128f","repo":"databendlabs/databend","slug":"the-header-tree-can-only-contain-dataheader","errorCode":null,"errorMessage":"The header tree can only contain DataHeader","messagePattern":"The header tree can only contain DataHeader","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/meta/control/src/reading.rs","lineNumber":65,"sourceCode":"            \"invalid data version: {:?}, This program version is {:?}; The latest compatible program version is: {:?}\",\n            version,\n            DATA_VERSION,\n            version.max_compatible_working_version(),\n        ));\n    }\n    Ok(version)\n}\n\npub fn read_version(first_line: &str) -> anyhow::Result<DataVersion> {\n    let (tree_name, kv_entry): (String, RaftStoreEntry) = serde_json::from_str(first_line)?;\n\n    let version = if tree_name == TREE_HEADER {\n        // There is a explicit header.\n        if let RaftStoreEntry::DataHeader { key, value } = &kv_entry {\n            assert_eq!(key, \"header\", \"The key can only be 'header'\");\n            value.0.version\n        } else {\n            unreachable!(\"The header tree can only contain DataHeader\");\n        }\n    } else {\n        // Without header, the data version is V0 by default.\n        DataVersion::V0\n    };\n\n    Ok(version)\n}\n","sourceCodeStart":47,"sourceCodeEnd":74,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/meta/control/src/reading.rs#L47-L74","documentation":"read_version reads the data version from the 'header' Raft tree. It asserts the header key equals 'header' and panics with unreachable!(\"The header tree can only contain DataHeader\") if the entry is any other RaftStoreEntry variant. The invariant is that the TREE_HEADER tree stores only DataHeader entries carrying an explicit version.","triggerScenarios":"Reading an entry from the header tree that is not RaftStoreEntry::DataHeader — e.g. corrupted/legacy on-disk data, a writer that stored a wrong entry type in the header tree, or entries written by an older version before the DataHeader format existed.","commonSituations":"Opening a meta-service data directory after an upgrade or downgrade across schema versions; disk corruption; hand-copying or merging raft-log directories between nodes.","solutions":["Inspect the offending header-tree entry and repair or remove the invalid record.","Ensure all writers only store RaftStoreEntry::DataHeader (key 'header') in TREE_HEADER.","If this appears after an upgrade/downgrade, restore the data directory from a compatible backup instead of replaying it."],"exampleFix":"// before\n_ => unreachable!(\"The header tree can only contain DataHeader\"),\n// after\nother => return Err(anyhow!(\"header tree contains non-DataHeader entry: {:?}\", other)),","handlingStrategy":"type-guard","validationCode":"fn is_data_header(entry: &RaftStoreEntry) -> bool {\n    matches!(entry, RaftStoreEntry::DataHeader { .. })\n}","typeGuard":null,"tryCatchPattern":"let version = match &kv_entry {\n    RaftStoreEntry::DataHeader { key, value } if key == \"header\" => value.0.version,\n    other => {\n        error!(\"invalid header tree entry: {:?}\", other);\n        return Err(Error::CorruptedHeaderTree);\n    }\n};","preventionTips":["Only ever write RaftStoreEntry::DataHeader entries into the header tree.","Back up the meta data directory before upgrading or downgrading meta-service versions.","Monitor for disk corruption; do not hand-merge raft-log directories between nodes.","On this panic, restore from a known-good backup rather than replaying suspect data."],"tags":["rust","panic","raft","storage","data-corruption"],"backgroundTag":"internal-invariant-violation","analyzedSha":"288d84d76e20a2f8f7173bda9691eb6ece301aa9","analyzedAt":"2026-09-11T11:29:36.208Z","contentChangedAt":"2026-09-11T11:29:36.208Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}