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
- Check the registry entry for the `boolean_operation` proto node in document_node_definitions.rs matches the current `IDENTIFIER` constant.
- Restore/re-add the `DocumentNodeDefinition` if it was dropped in a refactor.
- Handle `None` gracefully: log and return before inserting anything, so the user's layers are untouched.
- 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
- Grep for an IDENTIFIER's use sites before renaming it
- Register editor-side definitions in the same commit as graphene_std node additions
- Add boolean-operation flows to registry-change test matrices
- Prefer let-else over expect in all graph-mutating handlers
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
- Solidify Stroke node should exist
- Morph node does not exist
- Auto-Tangents node does not exist
- Transform node does not exist
- Stroke node does not exist
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/d08daea6cac96c5e.
Report an issue: GitHub.