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
- Log proto_create.bytecode_witness_index to confirm the out-of-range value.
- Fix the producer to bound the field to 0..=65535 and to a valid witness index for the tx.
- Pre-validate the range before decoding and reject the block early.
- 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
- Range-check integer fields against fuel-core type bounds (u16 here) at the trust boundary.
- Only accept proto from producers that mirror fuel-core's encoder (u16 widened to u32).
- In fuzz tests, constrain generated integers to realistic ranges to keep corpora meaningful.
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
- Could not convert tx_index to target type: {}
- Missing transaction variant
- Could not convert receipts_root to Bytes32: {}
- Could not convert storage slot key to Bytes32: {}
- Could not convert storage slot value to Bytes32: {}
AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16).
Data as JSON: /api/errors/ab5d9e6bd7eda91d.
Report an issue: GitHub.