GraphiteEditor/Graphite · error

Boolean node does not exist

Error message

Boolean node does not exist

What it means

Panics when `resolve_proto_node_type(graphene_std::path_bool_nodes::boolean_operation::IDENTIFIER)` returns `None` in `insert_boolean_data`. Boolean operations are inserted as proto nodes into a layer's chain; the lookup hits the static `DOCUMENT_NODE_TYPES` registry keyed by `ProtoNodeIdentifier`. The expect asserts the boolean-operation proto node definition is registered — a build-time invariant that fails only on registry/identifier drift.

Source

Thrown at editor/src/messages/portfolio/document/graph_operation/utility_types.rs:87

	}

	/// Creates an artboard as the primary export for the document network.
	pub fn create_artboard(&mut self, new_id: NodeId, location: DVec2, dimensions: DVec2, background: Color, clip: bool) -> LayerNodeIdentifier {
		let artboard_node_template = resolve_network_node_type("Artboard").expect("Node").node_template_input_override([
			Some(NodeInput::type_default(list!(Artboard), true)),
			Some(NodeInput::type_default(list!(Graphic), true)),
			Some(NodeInput::value(TaggedValue::DVec2(location), false)),
			Some(NodeInput::value(TaggedValue::DVec2(dimensions), false)),
			Some(NodeInput::value(TaggedValue::Color(background), false)),
			Some(NodeInput::value(TaggedValue::Bool(clip), false)),
		]);
		self.network_interface.insert_node(new_id, artboard_node_template, &[]);
		LayerNodeIdentifier::new(new_id, self.network_interface)
	}

	pub fn insert_boolean_data(&mut self, operation: graphene_std::vector::misc::BooleanOperation, layer: LayerNodeIdentifier) {
		let boolean = resolve_proto_node_type(graphene_std::path_bool_nodes::boolean_operation::IDENTIFIER)
			.expect("Boolean node does not exist")
			.node_template_input_override([
				Some(NodeInput::type_default(list!(Graphic), true)),
				Some(NodeInput::value(TaggedValue::BooleanOperation(operation), false)),
			]);

		let boolean_id = NodeId::new();
		self.network_interface.insert_node(boolean_id, boolean, &[]);
		self.network_interface.move_node_to_chain_start(&boolean_id, layer, &[], self.import);
	}

	pub fn insert_blend_data(&mut self, layer: LayerNodeIdentifier, count: f64) -> NodeId {
		let blend = resolve_network_node_type("Blend")
			.expect("Blend node does not exist")
			.node_template_input_override([Some(NodeInput::type_default(list!(Graphic), true)), Some(NodeInput::value(TaggedValue::F64(count), false))]);

		let blend_id = NodeId::new();
		self.network_interface.insert_node(blend_id, blend, &[]);
		self.network_interface.move_node_to_chain_start(&blend_id, layer, &[], self.import);

View on GitHub (pinned to c507b35645)

Solutions

  1. Check the registry entry for the `boolean_operation` proto node in document_node_definitions.rs matches the current `IDENTIFIER` constant.
  2. Restore/re-add the `DocumentNodeDefinition` if it was dropped in a refactor.
  3. Handle `None` gracefully: log and return before inserting anything, so the user's layers are untouched.
  4. Add a registry-completeness test covering the identifiers used by `utility_types.rs`.

Example fix

// before
let boolean = resolve_proto_node_type(graphene_std::path_bool_nodes::boolean_operation::IDENTIFIER)
    .expect("Boolean node does not exist")
    .node_template_input_override([

// after
let Some(boolean_def) = resolve_proto_node_type(graphene_std::path_bool_nodes::boolean_operation::IDENTIFIER) else {
    log::error!("Boolean Operation proto node not registered; skipping boolean insert");
    return;
};
let boolean = boolean_def.node_template_input_override([
Defensive patterns

Strategy: validation

Validate before calling

// Before applying a boolean operation:
if document_node_definitions::resolve_proto_node_type(graphene_std::path_bool_nodes::boolean_operation::IDENTIFIER).is_none() {
    log::error!("Boolean Operation node not registered; command unavailable");
    return;
}

Type guard

fn boolean_operation_registered() -> bool {
    document_node_definitions::resolve_proto_node_type(graphene_std::path_bool_nodes::boolean_operation::IDENTIFIER).is_some()
}

Try / catch

// Rust has no try/catch; handle the Option before mutating the graph:
let Some(bool_def) = resolve_proto_node_type(graphene_std::path_bool_nodes::boolean_operation::IDENTIFIER) else {
    log::error!("Boolean node missing");
    return;
};

Prevention

When it happens

Trigger: Performing a boolean operation (union/subtract/intersect/difference) on selected layers, which calls `insert_boolean_data`. Fires when `path_bool_nodes::boolean_operation::IDENTIFIER` is not in the registry: the node moved out of `path_bool_nodes`, its IDENTIFIER changed, or its definition entry was never added.

Common situations: Moving boolean nodes between graphene_std modules and forgetting the registry update; renaming the node struct/IDENTIFIER; adding a new boolean implementation without registering its definition.

Related errors


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