FuelLabs/fuel-core · error · Error::Serialization
Could not convert blob witness_index to u16: {}
Error message
Could not convert blob witness_index to u16: {} What it means
Blob transactions reference their blob witness via BlobBody.witness_index, a u16 in fuel-core. The proto field is wider; u16::try_from fails for values above 65535 (or negative), raising this Error::Serialization while building the BlobBody.
Source
Thrown at crates/services/block_aggregator_api/src/blocks/old_block_source/convertor_adapter/proto_to_fuel_conversions.rs:841
.iter()
.map(input_from_proto_input)
.collect::<crate::result::Result<Vec<_>>>()?;
let outputs = proto_blob
.outputs
.iter()
.map(output_from_proto_output)
.collect::<crate::result::Result<Vec<_>>>()?;
let witnesses = proto_blob
.witnesses
.iter()
.map(|w| Ok(Witness::from(w.clone())))
.collect::<crate::result::Result<Vec<_>>>()?;
let blob_id = fuel_core_types::fuel_types::BlobId::try_from(
proto_blob.blob_id.as_slice(),
)
.map_err(|e| Error::Serialization(anyhow!(e)))?;
let witness_index = u16::try_from(proto_blob.witness_index).map_err(|e| {
Error::Serialization(anyhow!(
"Could not convert blob witness_index to u16: {}",
e
))
})?;
let body = BlobBody {
id: blob_id,
witness_index,
};
let blob_tx =
FuelTransaction::blob(body, policies, inputs, outputs, witnesses);
Ok(FuelTransaction::Blob(blob_tx))
}
}
}
fn input_from_proto_input(proto_input: &ProtoInput) -> crate::result::Result<Input> {View on GitHub (pinned to b9d4d170da)
Solutions
- Validate witness_index <= 65535 and < witnesses.len() before converting the Blob transaction
- Fix the producer to emit a real witness index (blob transactions must attach the blob as a witness)
- Map sentinel values explicitly during re-encoding rather than letting try_from fail
- Add encode/decode round-trip tests for blob transactions in the producer's test suite
Example fix
// before
let witness_index = u16::try_from(proto_blob.witness_index).map_err(...)?;
// after
let wi = proto_blob.witness_index;
if wi > u16::MAX as u32 || wi as usize >= proto_blob.witnesses.len() {
return Err(anyhow!("blob witness_index {wi} invalid with {} witnesses", proto_blob.witnesses.len()));
}
let witness_index = wi as u16; Defensive patterns
Strategy: validation
Validate before calling
fn blob_witness_index_ok(b: &ProtoBlob) -> bool {
b.witness_index <= u16::MAX as u32 && (b.witness_index as usize) < b.witnesses.len()
} Type guard
fn fits_u16(v: u32) -> bool { v <= u16::MAX as u32 } Try / catch
let witness_index = u16::try_from(b.witness_index)
.with_context(|| format!("blob witness_index {} with {} witnesses", b.witness_index, b.witnesses.len()))?; Prevention
- Blob transactions must attach the blob witness; validate index < witnesses.len() pre-send
- Never encode -1 or u32::MAX as witness_index
- Re-verify blob tx protos with a decode pass before broadcasting
When it happens
Trigger: A Blob proto with witness_index > 65535 — typically a sentinel (u32::MAX / -1) meaning 'no witness', or a corrupted/mis-encoded payload. Valid transactions keep this well under the witness count.
Common situations: Cross-language encoders omitting range checks; sentinel values for optional witnesses; fuzzed data; version skew where a newer field semantics was back-filled into an old producer.
Related errors
- Could not convert witness_index to u16: {}
- Could not convert subsection_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: {}
AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16).
Data as JSON: /api/errors/116326e82959e6a6.
Report an issue: GitHub.