{"record":{"id":"e7a85ef969911950","repo":"FuelLabs/sway","slug":"loaddataid-refers-to-a-non-existent-data-section","errorCode":null,"errorMessage":"`LoadDataId` refers to a non-existent data section entry","messagePattern":"`LoadDataId` refers to a non-existent data section entry","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sway-core/src/asm_generation/fuel/programs/allocated.rs","lineNumber":61,"sourceCode":"        //\n        // We reserve one data section pointer slot for each non-copy `LoadDataId`.\n        // The slots are filled in-place during the bytecode generation,\n        // which does not change the layout.\n        //\n        // We freeze the worst-case offset of the configurables region, pessimistically\n        // assuming that every far jump whose realization can insert a target word\n        // into the data section does insert one. `AddrDataId`s pointing to\n        // configurables are sized against this worst-case offset. Note that in practice\n        // this \"pessimization\" almost never results in generating two instructions\n        // `MOVI` + `ADD` instead of one `ADDI`.\n        let num_non_copy_loads = abstract_ops\n            .ops\n            .iter()\n            .filter(|op| match &op.opcode {\n                Either::Left(AllocatedInstruction::LoadDataId(_, data_id)) => !self\n                    .data_section\n                    .has_copy_type(data_id)\n                    .expect(\"`LoadDataId` refers to a non-existent data section entry\"),\n                _ => false,\n            })\n            .count();\n        self.data_section.reserve_pointer_slots(num_non_copy_loads);\n\n        let (far_jump_sizes, worst_case_far_jump_words) = abstract_ops.collect_far_jumps();\n        self.data_section\n            .freeze_configurables_base_offset(8 * worst_case_far_jump_words);\n\n        let (realized_ops, mut label_offsets) =\n            abstract_ops.lower_to_realized_ops(&mut self.data_section, &far_jump_sizes)?;\n        let ops = realized_ops.lower_to_allocated_ops();\n\n        // Collect the entry point offsets.\n        let entries = self\n            .entries\n            .into_iter()\n            .map(|(selector, label, name, test_decl_ref)| {","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/FuelLabs/sway/blob/dad95cc42b0383b4e3bacdeda9766565aa584a92/sway-core/src/asm_generation/fuel/programs/allocated.rs#L43-L79","documentation":"During conversion of the allocated abstract instruction set into a final program, the compiler counts non-copy LoadDataId ops (loads whose target is not a small copy-type value) to reserve a pointer slot for each one. Counting requires has_copy_type(data_id), which returns None when the data id does not exist in the data section. The panic fires because a LoadDataId references a DataId that was never inserted into (or was removed from) the data section — an internal invariant violation of the lowering passes.","triggerScenarios":"Thrown at sway-core/src/asm_generation/fuel/programs/allocated.rs:61 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Verify every LoadDataId emitted during abstract IR lowering is accompanied by inserting the corresponding entry into the data section","Check that data section deduplication/pruning passes do not remove entries still referenced by emitted LoadDataId ops","Reproduce with the failing contract and trace the DataId index/region back to where the load op was created"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"dad95cc42b0383b4e3bacdeda9766565aa584a92","analyzedAt":"2026-09-04T20:02:14.068Z","contentChangedAt":"2026-09-04T20:02:14.068Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}