FuelLabs/fuel-core · error · Error::Serialization
Could not convert subsection_index to u16: {}
Error message
Could not convert subsection_index to u16: {} What it means
Upload bytecode is split into subsections; the proto subsection_index field is wider than the u16 the fuel-core UploadBody expects. u16::try_from fails for values above 65535 (or negative i32), yielding this serialization error during Upload transaction conversion.
Source
Thrown at crates/services/block_aggregator_api/src/blocks/old_block_source/convertor_adapter/proto_to_fuel_conversions.rs:777
.iter()
.map(|w| Ok(Witness::from(w.clone())))
.collect::<crate::result::Result<Vec<_>>>()?;
let root = Bytes32::try_from(proto_upload.root.as_slice()).map_err(|e| {
Error::Serialization(anyhow!(
"Could not convert upload root to Bytes32: {}",
e
))
})?;
let witness_index =
u16::try_from(proto_upload.witness_index).map_err(|e| {
Error::Serialization(anyhow!(
"Could not convert witness_index to u16: {}",
e
))
})?;
let subsection_index =
u16::try_from(proto_upload.subsection_index).map_err(|e| {
Error::Serialization(anyhow!(
"Could not convert subsection_index to u16: {}",
e
))
})?;
let subsections_number = u16::try_from(proto_upload.subsections_number)
.map_err(|e| {
Error::Serialization(anyhow!(
"Could not convert subsections_number to u16: {}",
e
))
})?;
let proof_set = proto_upload
.proof_set
.iter()
.map(|entry| {
Bytes32::try_from(entry.as_slice()).map_err(|e| {
Error::Serialization(anyhow!(
"Could not convert proof_set entry to Bytes32: {}",View on GitHub (pinned to b9d4d170da)
Solutions
- Validate subsection_index <= 65535 and < subsections_number before conversion
- Align the subsection chunk-size constant between the uploading client and this crate so indices fit u16
- Reject and re-upload oversized blobs: if a blob needs more than 65536 subsections, split the upload differently
- Log the offending transaction id and blob root to identify which producer emitted the bad index
Example fix
// before
let subsection_index = u16::try_from(proto_upload.subsection_index).map_err(...)?;
// after
let si = proto_upload.subsection_index;
if si > u16::MAX as u32 {
return Err(anyhow!("subsection_index {si} exceeds u16"));
}
let subsection_index = si as u16; Defensive patterns
Strategy: validation
Validate before calling
fn upload_subsection_index_ok(u: &ProtoUpload) -> bool {
u.subsection_index <= u16::MAX as u32 && u.subsection_index < u.subsections_number
} Type guard
fn fits_u16(v: u32) -> bool { v <= u16::MAX as u32 } Try / catch
let subsection_index = u16::try_from(u.subsection_index)
.with_context(|| format!("subsection_index {} in tx {:?}", u.subsection_index, tx_id))?; Prevention
- Share the subsection chunk-size constant between client and chain code
- Cross-validate subsection_index < subsections_number whenever both are present
- Fuzz upload protos with oversized indices to confirm early rejection
When it happens
Trigger: An Upload proto with subsection_index > 65535 — e.g., a producer that computed subsections with a different chunk size, or corrupted/garbage data. A defaulted (0) field never triggers this; only an out-of-range encoded value does.
Common situations: Producer/consumer disagree on subsection chunk size so the index overflows u16; fuzzed or corrupted payloads; mis-typed int32 encoding from another language.
Related errors
- Could not convert witness_index to u16: {}
- Could not convert subsections_number to u16: {}
- Could not convert upload root to Bytes32: {}
- Could not convert proof_set entry to Bytes32: {}
- Could not convert blob witness_index to u16: {}
AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16).
Data as JSON: /api/errors/3f7d863dd3d88896.
Report an issue: GitHub.