EpicGames/lore · error · io::Error (InvalidData)
level header file has unsupported version
Error message
level header file has unsupported version {}, expected {} What it means
After the magic check, `read_level_header_file` validates `header.version` against `MARKER_VERSION`. A mismatch means the marker file was written by a different (older or newer) lore-storage on-disk format that this build cannot read. It fails with `ErrorKind::InvalidData` reporting both versions.
Solutions
- Upgrade lore-storage to the version that wrote `MARKER_VERSION` (the 'expected' value in the message shows what this build needs).
- Run any provided migration tooling to convert old-format stores.
- Re-seed/rebuild the store if no migration path exists.
Example fix
// before let header = read_level_marker(dir).await?; // fails: unsupported version 2 // after // pin the crate version that wrote the store, or migrate first: // Cargo.toml: lore-storage = "= <version matching MARKER_VERSION>" let header = read_level_marker(dir).await?;
Defensive patterns
Strategy: try-catch
Validate before calling
let bytes = tokio::fs::read(&header_path).await?;
let version = u32::from_le_bytes(bytes[4..8].try_into()?);
if version != MARKER_VERSION { /* migrate or use matching crate version */ } Try / catch
match read_level_marker(dir).await {
Err(e) if e.kind() == io::ErrorKind::InvalidData => {
eprintln!("store written by a different lore-storage version; migrate first");
}
other => other?,
} Prevention
- Pin the lore-storage version in CI so all machines read stores with the same format.
- Run migrations before opening stores written by older versions.
- Don't downgrade the dependency against an existing store directory.
When it happens
Trigger: Opening a store whose level marker files were written by a different lore-storage version — typically upgrading or downgrading the library, or mixing store directories between versions.
Common situations: Rolling back a dependency version, copying a store directory between machines running different builds, or a beta/nightly format change without a migration path.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Pager process stdin not available
- bytes exceeds the byte whole-file limit; open the file and…
- unsupported LORE_IO_BACKEND
- file ended before the requested read length
- file refused further writes
AI-assisted analysis of EpicGames/lore@074eb0b0d1 (2026-09-13).
Data as JSON: /api/errors/b904e4766955d0f9.
Report an issue: GitHub.
Appendix: source
Thrown at lore-storage/src/local/fan_out.rs:408
std::io::ErrorKind::UnexpectedEof,
format!(
"level header file is {} bytes, expected {expected}",
bytes.len()
),
));
}
header.as_mut_bytes().copy_from_slice(&bytes[..expected]);
if header.magic != MARKER_MAGIC {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!(
"level header file has invalid magic 0x{:08x}, expected 0x{:08x}",
header.magic, MARKER_MAGIC
),
));
}
if header.version != MARKER_VERSION {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!(
"level header file has unsupported version {}, expected {}",
header.version, MARKER_VERSION
),
));
}
Ok(Some(header.bucket_count as usize))
}
/// The serialized level header as the one segment a gather writes.
///
/// Fixed size — the header's length is a compile-time constant — and behind a pointer, because
/// [`lore_io::StableBufList`] requires a segment to keep its address when the value moves and the
/// ring backend moves the segment list into its operation entry after taking the pointers.
struct LevelHeaderSegment(Box<[u8; size_of::<LevelMarkerHeader>()]>);
impl lore_io::StableBufList for LevelHeaderSegment {View on GitHub (pinned to 074eb0b0d1)