{"record":{"id":"a13d248d1ed9bda1","repo":"wasmerio/wasmer","slug":"internal-error-allocated-index-allocated-index","errorCode":null,"errorMessage":"Internal error: allocated index {allocated_index} does not match expected index {index}","messagePattern":"Internal error: allocated index (.+?) does not match expected index (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/wasix/src/state/linker/instance_group/table.rs","lineNumber":171,"sourceCode":"\n        self.place_in_function_table_at(store, func.clone(), function_table_index)\n            .map_err(LinkError::TableAllocationError)?;\n\n        Ok(())\n    }\n\n    pub(super) fn apply_function_table_allocation(\n        &mut self,\n        store: &mut impl AsStoreMut,\n        index: u32,\n        size: u32,\n    ) -> Result<(), LinkError> {\n        trace!(index, \"Applying function table allocation\");\n        let allocated_index = self\n            .allocate_function_table(store, size, 0)\n            .map_err(LinkError::TableAllocationError)? as u32;\n        if allocated_index != index {\n            panic!(\n                \"Internal error: allocated index {allocated_index} does not match expected index {index}\"\n            );\n        }\n        Ok(())\n    }\n}\n","sourceCodeStart":153,"sourceCodeEnd":178,"githubUrl":"https://github.com/wasmerio/wasmer/blob/8c4b9ee9d33fb2068863fbb3d328683e7e6ff7f5/lib/wasix/src/state/linker/instance_group/table.rs#L153-L178","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Apply DL operations in the exact order they were recorded, into a fresh instance group","Do not interleave manual allocate_function_table calls with replayed allocations","Re-record the operation log from the current run instead of reusing a stale one","Verify only one code path mutates the function table per group"],"exampleFix":"// before: stale op applied to a mutated table\nfor op in recorded_ops { group.apply_dl_operation(store, &state, op)?; }\n// after: replay into a fresh group created for this run\nlet group = InstanceGroup::new();\nfor op in recorded_ops { group.apply_dl_operation(store, &state, op)?; }","handlingStrategy":"validation","validationCode":"fn replay(ops: Vec<DlOperation>) {\n    assert!(!ops_replayed, \"replay each op log exactly once, into a fresh group\");\n    ops_replayed = true;\n    // apply ops in recorded order with no interleaved manual allocations\n}","typeGuard":"fn is_contiguous_allocation(prev_index: u64, size: u64, next: u64) -> bool {\n    next == prev_index + size\n}","tryCatchPattern":null,"preventionTips":["Replay DL operations in recorded order into a fresh group","Never interleave manual allocate_function_table calls with replays","Re-record op logs after any linker version or module change","Keep a single writer to the function table per group"],"tags":["linker","table-allocation","internal-invariant","panic"],"backgroundTag":"linker-table-base-mismatch","analyzedSha":"8c4b9ee9d33fb2068863fbb3d328683e7e6ff7f5","analyzedAt":"2026-09-01T23:06:31.009Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}