FyroxEngine/Fyrox · warning

There are multiple original nodes for

Error message

There are multiple original nodes for {:?}! Previous was {:?}. This can happen if a respective node was deleted.

What it means

In remap_handles (during copy_node of an instantiated resource), it builds a map from each instance node's original_handle_in_resource to the new node handle. If two instance nodes claim the same original handle, insert returns the previous mapping and this warning fires — the graph structure is inconsistent (usually because a node was deleted but its original handle was reused/left behind).

Solutions

  1. Find the duplicated nodes (the message prints both handles) and delete the stale duplicate from the instance.
  2. Re-instantiate the resource into a fresh graph instead of patching the corrupted instance.
  3. If the warning appears after deletes, perform deletes through the editor so integrity is maintained and restore_integrity can run.
  4. Inspect the saved scene file for two nodes with the same original_handle and fix it by hand as a last resort.

Example fix

// before
// scene: node A (orig 5:0) and duplicate node B (orig 5:0)
// after
graph.remove_node(duplicate_handle); // remove B before copy_node/instantiation sync
Defensive patterns

Strategy: validation

Validate before calling

// detect duplicate original-handle mappings before remap
fn duplicates(instance: &SceneResourceInstance) -> HashMap<Handle<Node>, usize> {
    let mut counts = HashMap::new();
    for n in instance.nodes() {
        *counts.entry(n.original_handle_in_resource()).or_insert(0) += 1;
    }
    counts.into_iter().filter(|(_, c)| *c > 1).collect()
}

Try / catch

let dup = duplicates(&instance);
if !dup.is_empty() {
    for (orig, count) in dup { log::warn!("{count} nodes claim original {orig:?}; clean up before sync"); }
}

Prevention

When it happens

Trigger: copy_node -> remap_handles finds multiple instance nodes with identical original_handle_in_resource — duplicate instance nodes referencing one resource node, often after a node was deleted improperly.

Common situations: Deleting nodes from a resource instance without cleaning original-handle mappings; duplicated subgraphs pasted into an instance; scenes saved mid-edit in the editor with stale duplicates.

Related errors


AI-assisted analysis of FyroxEngine/Fyrox@76c91aad8e (2026-09-10). Data as JSON: /api/errors/6ccf20f0bcb3e0f2. Report an issue: GitHub.

Appendix: source

Thrown at fyrox-graph/src/lib.rs:1472

    /// instance root. Then we must find all inheritable properties and try to remap them to instance handles.
    fn remap_handles(&mut self, instances: &[(Handle<Self::NodeWrapper>, Resource<Self::Prefab>)]) {
        for (instance_root, resource) in instances {
            // Prepare old -> new handle mapping first by walking over the graph
            // starting from instance root.
            let mut old_new_mapping = NodeHandleMap::default();
            let mut traverse_stack = vec![*instance_root];
            while let Some(node_handle) = traverse_stack.pop() {
                let Ok(node) = self.try_get_node(node_handle) else {
                    continue;
                };
                if let Some(node_resource) = node.resource().as_ref() {
                    // We're interested only in instance nodes.
                    if node_resource == resource {
                        let previous_mapping =
                            old_new_mapping.insert(node.original_handle_in_resource(), node_handle);
                        // There should be no such node.
                        if previous_mapping.is_some() {
                            Log::warn(format!(
                                "There are multiple original nodes for {:?}! Previous was {:?}. \
                                This can happen if a respective node was deleted.",
                                node_handle,
                                node.original_handle_in_resource()
                            ))
                        }
                    }
                }

                traverse_stack.extend_from_slice(node.children());
            }

            // Lastly, remap handles. We can't do this in single pass because there could
            // be cross references.
            for handle in old_new_mapping.inner().values() {
                old_new_mapping.remap_inheritable_handles(
                    self.node_mut(*handle),
                    &[TypeId::of::<UntypedResource>()],

View on GitHub (pinned to 76c91aad8e)