FuelLabs/fuel-core · error
Fragments use different compressions.
Error message
Fragments use different compressions.
What it means
Snapshot fragments merge only when their parquet compression settings match: merging a Parquet fragment compressed with one ZstdCompressionLevel into another with a different level fails with 'Fragments use different compressions.' (crates/chain-config/src/config/state/writer.rs:187). The compression level is part of the fragment identity because table data is concatenated verbatim. Note the tables vec is extended before the check runs, so a failed merge must be treated as poisoned — the merged value only exists on success.
Source
Thrown at crates/chain-config/src/config/state/writer.rs:187
builder: other_builder,
..
},
) => {
builder.merge(other_builder);
}
#[cfg(feature = "parquet")]
(
FragmentData::Parquet {
tables,
compression,
},
FragmentData::Parquet {
tables: their_tables,
compression: their_compression,
},
) => {
tables.extend(their_tables);
anyhow::ensure!(
*compression == their_compression,
"Fragments use different compressions."
)
}
#[cfg(feature = "parquet")]
(a, b) => anyhow::bail!(
"Fragments don't have the same encoding and cannot be merged. Fragments: {a:?} and {b:?}"
),
};
Ok(self)
}
}
#[derive(Debug, Clone)]
pub struct SnapshotFragment {
dir: PathBuf,
data: FragmentData,View on GitHub (pinned to b9d4d170da)
Solutions
- Produce every fragment with the same ZstdCompressionLevel before merging.
- Centralize the compression level in one config value shared by all writers/workers.
- If levels already differ, re-encode the divergent fragment at the target level instead of merging mixed data.
Example fix
// before
let merged = fragment_a.merge(fragment_b)?; // level 3 vs level 22 → error
// after — one shared level for every fragment
let level = ZstdCompressionLevel::try_from(3u8)?; // same value everywhere
let a = FragmentData::Parquet { tables: a_tables, compression: level };
let b = FragmentData::Parquet { tables: b_tables, compression: level }; Defensive patterns
Strategy: validation
Validate before calling
// Configure every fragment writer from one shared level so merges always agree let level = ZstdCompressionLevel::try_from(3u8)?; // single source of truth // pass `level` to every writer/worker that produces fragments
Type guard
if let (
FragmentData::Parquet { compression: a, .. },
FragmentData::Parquet { compression: b, .. },
) = (&fragment_a.data, &fragment_b.data)
{
anyhow::ensure!(a == b, "refusing to merge compressions {a:?} and {b:?}");
} Try / catch
match fragment_a.merge(fragment_b) {
Err(e) if e.to_string().contains("different compressions") => {
// re-encode one fragment at the other's level, then merge again
reencode_fragment(&fragment_b, target_level)?;
}
other => other?,
} Prevention
- Centralize the compression level in one config shared by all snapshot workers.
- Record the level in fragment metadata so merges can pre-check compatibility.
- Never mix fragments produced before and after a compression-config change.
When it happens
Trigger: Calling merge between two fragments produced with different ZstdCompressionLevel values — e.g. parallel snapshot workers each configured with their own level.
Common situations: Distributed snapshot generation where worker configs drift; changing compression config between runs and merging fragments from old and new runs.
Related errors
- Fragments don't have the same encoding and cannot be merged.
- Missing code for contract: {id}
- Missing utxo for contract: {id}
- No block height found
- No config found
AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16).
Data as JSON: /api/errors/48bf0f942c1780d6.
Report an issue: GitHub.