FuelLabs/sway · error

`data_id` references data non-existent in the data section

Error message

`data_id` references data non-existent in the data section

What it means

In finalize, after freezing the data section layout, the compiler walks the allocated ops to fill reserved pointer slots for non-copy LoadDataId instructions. Determining whether a load is non-copy calls has_copy_type(data_id), which returns None when the DataId has no matching entry in the data section. The panic indicates a load instruction references data that is absent from the data section at finalization time — an internal compiler invariant violation, typically caused by a lowering or optimization pass that dropped or never registered the referenced entry.

Source

Thrown at sway-core/src/asm_generation/fuel/programs/final.rs:67

        // Word-align the data section by appending NOOPs if needed.
        let mut offset_to_data_section_in_bytes: u64 =
            ops.iter().map(|op| op.size_in_bytes(&data_section)).sum();
        if !offset_to_data_section_in_bytes.is_multiple_of(8) {
            ops.push(AllocatedOp {
                opcode: AllocatedInstruction::NOOP,
                comment: "word-align the data section".into(),
                owning_span: None,
            });
            offset_to_data_section_in_bytes += 4;
        }

        // Fill the reserved pointer slots.
        let mut offset_from_instr_start = 0;
        for op in &ops {
            if let AllocatedInstruction::LoadDataId(_reg, data_id) = &op.opcode {
                if !data_section
                    .has_copy_type(data_id)
                    .expect("`data_id` references data non-existent in the data section")
                {
                    // A non-copy load loads a pointer to its target entry instead of
                    // the entry itself. The pointer is stored in one of the reserved
                    // pointer slots, and its value is relative to the load
                    // instruction: the realized load adds `$pc` to it.
                    let offset_bytes = data_section.data_id_to_offset(data_id) as u64;
                    // The -4 is because $pc is added in the *next* instruction.
                    let pointer_offset_from_current_instr =
                        offset_to_data_section_in_bytes - offset_from_instr_start + offset_bytes
                            - 4;
                    data_section.append_pointer(pointer_offset_from_current_instr);
                }
            }
            offset_from_instr_start += op.size_in_bytes(&data_section);
        }

        FinalizedAsm {
            data_section,

View on GitHub (pinned to dad95cc42b)

Solutions

  1. Ensure every pass that emits LoadDataId also registers its target entry in the data section before finalize runs
  2. Check data-section pruning/dedup passes for removing entries still referenced by emitted loads
  3. Trace the failing DataId (idx, region) back through lowering to find the pass that dropped the entry
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at sway-core/src/asm_generation/fuel/programs/final.rs:67 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of FuelLabs/sway@dad95cc42b (2026-09-04). Data as JSON: /api/errors/3936739b6c9440e1. Report an issue: GitHub.