GraphiteEditor/Graphite · error

node not found in lookup table

Error message

node not found in lookup table

What it means

During topological reordering of a ProtoNetwork, every node id is remapped through new_positions, which only contains nodes present in the topological order. Any reference to a node outside that order misses the lookup table and panics — the network references something the compiled order does not include.

Source

Thrown at node-graph/graph-craft/src/proto.rs:521

	/// Sort the nodes vec so it is in a topological order. This ensures that no node takes an input from a node that is found later in the list.
	fn reorder_ids(&mut self) -> Result<(), String> {
		let (order, _id_map) = self.topological_sort()?;

		// // Map of node ids to their current index in the nodes vector
		// let current_positions: FxHashMap<_, _> = self.nodes.iter().enumerate().map(|(pos, (id, _))| (*id, pos)).collect();

		// // Map of node ids to their new index based on topological order
		let new_positions: FxHashMap<_, _> = order.iter().enumerate().map(|(pos, id)| (self.nodes[id.0 as usize].0, pos)).collect();
		// assert_eq!(id_map, current_positions);

		// Create a new nodes vector based on the topological order

		let mut new_nodes = Vec::with_capacity(order.len());
		for (index, &id) in order.iter().enumerate() {
			let mut node = std::mem::take(&mut self.nodes[id.0 as usize].1);
			// Update node references to reflect the new order
			node.map_ids(|id| NodeId(*new_positions.get(&id).expect("node not found in lookup table") as u64));
			new_nodes.push((NodeId(index as u64), node));
		}

		// Update node references to reflect the new order
		// new_nodes.iter_mut().for_each(|(_, node)| {
		// 	node.map_ids(|id| *new_positions.get(&id).expect("node not found in lookup table"), false);
		// });

		// Update the nodes vector and other references
		self.nodes = new_nodes;
		self.inputs = self.inputs.iter().filter_map(|id| new_positions.get(id).map(|x| NodeId(*x as u64))).collect();
		self.output = NodeId(*new_positions.get(&self.output).unwrap() as u64);

		assert_eq!(order.len(), self.nodes.len());
		Ok(())
	}
}
#[derive(Clone, PartialEq, serde::Serialize, serde::Deserialize)]

View on GitHub (pinned to c507b35645)

Solutions

  1. Reproduce with the failing document and compare referenced ids against the topological order to find the excluded node
  2. Ensure every referenced node is reachable from the network inputs/output before compiling
  3. Report the minimal failing graph upstream — the compiler should return an error, not panic, on out-of-order references

Example fix

// before
node.map_ids(|id| NodeId(*new_positions.get(&id).expect("node not found in lookup table") as u64));

// after
node.map_ids(|id| match new_positions.get(&id) {
	Some(pos) => NodeId(*pos as u64),
	None => {
		log::warn!("reference to node {id:?} outside topological order; leaving as-is");
		id
	}
});
Defensive patterns

Strategy: validation

Validate before calling

// before compiling, every referenced id must appear in the topological order
let referenced: HashSet<NodeId> = /* collect from inputs/output */;
assert!(referenced.iter().all(|id| order.contains(id)), "graph references nodes outside the topological order");

Prevention

When it happens

Trigger: A node reference pointing at a node excluded from the DFS topological order (disconnected, or only referenced from filtered inputs); nested network inlining that leaves stale ids; graphs where the ordering pass drops nodes.

Common situations: Compiling macro-generated or hand-assembled networks; version drift between graph-craft's compiler expectations and the document structure feeding it.

Related errors


AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16). Data as JSON: /api/errors/3a4ab8dd3da67c3c. Report an issue: GitHub.