FuelLabs/fuel-core · error · Error::Serialization

Could not convert bytecode_witness_index to u16: {}

Error message

Could not convert bytecode_witness_index to u16: {}

What it means

The proto Create transaction stores bytecode_witness_index as a wide uint (the fuel-to-proto direction widens fuel-core's u16), and the reverse conversion u16::try_from fails when the value exceeds 65535, wrapped as Error::Serialization. fuel-core's Create transaction type requires u16, so out-of-range values are unrepresentable.

Source

Thrown at crates/services/block_aggregator_api/src/blocks/old_block_source/convertor_adapter/proto_to_fuel_conversions.rs:652

                .iter()
                .map(output_from_proto_output)
                .collect::<crate::result::Result<Vec<_>>>()?;
            let witnesses = proto_create
                .witnesses
                .iter()
                .map(|w| Ok(Witness::from(w.clone())))
                .collect::<crate::result::Result<Vec<_>>>()?;
            let storage_slots = proto_create
                .storage_slots
                .iter()
                .map(storage_slot_from_proto)
                .collect::<crate::result::Result<Vec<_>>>()?;
            let salt =
                fuel_core_types::fuel_types::Salt::try_from(proto_create.salt.as_slice())
                    .map_err(|e| Error::Serialization(anyhow!(e)))?;
            let bytecode_witness_index =
                u16::try_from(proto_create.bytecode_witness_index).map_err(|e| {
                    Error::Serialization(anyhow!(
                        "Could not convert bytecode_witness_index to u16: {}",
                        e
                    ))
                })?;

            let create_tx = FuelTransaction::create(
                bytecode_witness_index,
                policies,
                salt,
                storage_slots,
                inputs,
                outputs,
                witnesses,
            );

            Ok(FuelTransaction::Create(create_tx))
        }
        ProtoTransactionVariant::Mint(proto_mint) => {

View on GitHub (pinned to b9d4d170da)

Solutions

  1. Log proto_create.bytecode_witness_index to confirm the out-of-range value.
  2. Fix the producer to bound the field to 0..=65535 and to a valid witness index for the tx.
  3. Pre-validate the range before decoding and reject the block early.
  4. Treat payloads from non-fuel-core encoders as untrusted input.

Example fix

// before
let bytecode_witness_index =
    u16::try_from(proto_create.bytecode_witness_index).map_err(|e| {
        Error::Serialization(anyhow!("Could not convert bytecode_witness_index to u16: {}", e))
    })?;

// after: caller-side range check with context
if proto_create.bytecode_witness_index > u16::MAX as u32 {
    return Err(Error::Serialization(anyhow::anyhow!(
        "bytecode_witness_index {} exceeds u16::MAX",
        proto_create.bytecode_witness_index
    )));
}
Defensive patterns

Strategy: validation

Validate before calling

fn bytecode_witness_index_valid(create: &ProtoCreate) -> bool {
    create.bytecode_witness_index <= u16::MAX as u32
}

Type guard

fn bytecode_witness_index_in_range(create: &ProtoCreate) -> bool {
    create.bytecode_witness_index <= u16::MAX as u32
}

Try / catch

match tx_from_proto_tx(t) {
    Ok(tx) => txs.push(tx),
    Err(Error::Serialization(ctx)) if ctx.to_string().contains("bytecode_witness_index") => {
        tracing::warn!(idx = create.bytecode_witness_index, "rejecting Create tx with out-of-range witness index");
        return Err(Error::Serialization(ctx));
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Decoding a ProtoTransaction::Create whose bytecode_witness_index exceeds u16::MAX - only possible when the proto was not produced by fuel-core's own encoder (which always writes valid u16 values), e.g. hand-crafted messages, corrupted integers, or fuzz input.

Common situations: Third-party tools generating the protobuf format without fuel-core's bounds; fuzz/corpus testing with unconstrained integers; corrupted numeric fields.

Related errors


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