wasmerio/wasmer · error

Internal error: allocated index {allocated_index} does not m

Error message

Internal error: allocated index {allocated_index} does not match expected index {index}

What it means

apply_function_table_allocation allocates table space via allocate_function_table and then asserts the returned base index equals the index recorded in the DL operation. A mismatch means the allocator's state no longer matches the serialized/recorded allocation, so all precomputed function pointers would be off. This is an internal consistency check for replaying dynamic-link operations.

Source

Thrown at lib/wasix/src/state/linker/instance_group/table.rs:171

        self.place_in_function_table_at(store, func.clone(), function_table_index)
            .map_err(LinkError::TableAllocationError)?;

        Ok(())
    }

    pub(super) fn apply_function_table_allocation(
        &mut self,
        store: &mut impl AsStoreMut,
        index: u32,
        size: u32,
    ) -> Result<(), LinkError> {
        trace!(index, "Applying function table allocation");
        let allocated_index = self
            .allocate_function_table(store, size, 0)
            .map_err(LinkError::TableAllocationError)? as u32;
        if allocated_index != index {
            panic!(
                "Internal error: allocated index {allocated_index} does not match expected index {index}"
            );
        }
        Ok(())
    }
}

View on GitHub (pinned to 8c4b9ee9d3)

Solutions

  1. Apply DL operations in the exact order they were recorded, into a fresh instance group
  2. Do not interleave manual allocate_function_table calls with replayed allocations
  3. Re-record the operation log from the current run instead of reusing a stale one
  4. Verify only one code path mutates the function table per group

Example fix

// before: stale op applied to a mutated table
for op in recorded_ops { group.apply_dl_operation(store, &state, op)?; }
// after: replay into a fresh group created for this run
let group = InstanceGroup::new();
for op in recorded_ops { group.apply_dl_operation(store, &state, op)?; }
Defensive patterns

Strategy: validation

Validate before calling

fn replay(ops: Vec<DlOperation>) {
    assert!(!ops_replayed, "replay each op log exactly once, into a fresh group");
    ops_replayed = true;
    // apply ops in recorded order with no interleaved manual allocations
}

Type guard

fn is_contiguous_allocation(prev_index: u64, size: u64, next: u64) -> bool {
    next == prev_index + size
}

Prevention

When it happens

Trigger: apply_dl_operation replaying an allocation whose recorded index differs from the allocator's current position; interleaved table allocations between recording and applying; applying operations out of order or applying an old operation log to a reused group.

Common situations: Replaying a DL operation log into a group that already made other allocations; concurrent/interleaved dlopen flows mutating the table between record and apply; state snapshots mixed across groups.

Related errors


AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01). Data as JSON: /api/errors/a13d248d1ed9bda1. Report an issue: GitHub.