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

  1. Validate subsection_index <= 65535 and < subsections_number before conversion
  2. Align the subsection chunk-size constant between the uploading client and this crate so indices fit u16
  3. Reject and re-upload oversized blobs: if a blob needs more than 65536 subsections, split the upload differently
  4. 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

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


AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16). Data as JSON: /api/errors/3f7d863dd3d88896. Report an issue: GitHub.