{"record":{"id":"3f7d863dd3d88896","repo":"FuelLabs/fuel-core","slug":"could-not-convert-subsection-index-to-u16","errorCode":null,"errorMessage":"Could not convert subsection_index to u16: {}","messagePattern":"Could not convert subsection_index to u16: (.+?)","errorType":"exception","errorClass":"Error::Serialization","httpStatus":null,"severity":"error","filePath":"crates/services/block_aggregator_api/src/blocks/old_block_source/convertor_adapter/proto_to_fuel_conversions.rs","lineNumber":777,"sourceCode":"                .iter()\n                .map(|w| Ok(Witness::from(w.clone())))\n                .collect::<crate::result::Result<Vec<_>>>()?;\n            let root = Bytes32::try_from(proto_upload.root.as_slice()).map_err(|e| {\n                Error::Serialization(anyhow!(\n                    \"Could not convert upload root to Bytes32: {}\",\n                    e\n                ))\n            })?;\n            let witness_index =\n                u16::try_from(proto_upload.witness_index).map_err(|e| {\n                    Error::Serialization(anyhow!(\n                        \"Could not convert witness_index to u16: {}\",\n                        e\n                    ))\n                })?;\n            let subsection_index =\n                u16::try_from(proto_upload.subsection_index).map_err(|e| {\n                    Error::Serialization(anyhow!(\n                        \"Could not convert subsection_index to u16: {}\",\n                        e\n                    ))\n                })?;\n            let subsections_number = u16::try_from(proto_upload.subsections_number)\n                .map_err(|e| {\n                    Error::Serialization(anyhow!(\n                        \"Could not convert subsections_number to u16: {}\",\n                        e\n                    ))\n                })?;\n            let proof_set = proto_upload\n                .proof_set\n                .iter()\n                .map(|entry| {\n                    Bytes32::try_from(entry.as_slice()).map_err(|e| {\n                        Error::Serialization(anyhow!(\n                            \"Could not convert proof_set entry to Bytes32: {}\",","sourceCodeStart":759,"sourceCodeEnd":795,"githubUrl":"https://github.com/FuelLabs/fuel-core/blob/b9d4d170da3a31c9ace5f963d633b326348e0d42/crates/services/block_aggregator_api/src/blocks/old_block_source/convertor_adapter/proto_to_fuel_conversions.rs#L759-L795","documentation":"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.","triggerScenarios":"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.","commonSituations":"Producer/consumer disagree on subsection chunk size so the index overflows u16; fuzzed or corrupted payloads; mis-typed int32 encoding from another language.","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"],"exampleFix":"// before\nlet subsection_index = u16::try_from(proto_upload.subsection_index).map_err(...)?;\n\n// after\nlet si = proto_upload.subsection_index;\nif si > u16::MAX as u32 {\n    return Err(anyhow!(\"subsection_index {si} exceeds u16\"));\n}\nlet subsection_index = si as u16;","handlingStrategy":"validation","validationCode":"fn upload_subsection_index_ok(u: &ProtoUpload) -> bool {\n    u.subsection_index <= u16::MAX as u32 && u.subsection_index < u.subsections_number\n}","typeGuard":"fn fits_u16(v: u32) -> bool { v <= u16::MAX as u32 }","tryCatchPattern":"let subsection_index = u16::try_from(u.subsection_index)\n    .with_context(|| format!(\"subsection_index {} in tx {:?}\", u.subsection_index, tx_id))?;","preventionTips":["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"],"tags":["rust","fuel","protobuf","serialization","upload-transaction","integer-overflow","validation"],"backgroundTag":null,"analyzedSha":"b9d4d170da3a31c9ace5f963d633b326348e0d42","analyzedAt":"2026-08-16T08:56:42.692Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}