{"record":{"id":"d08daea6cac96c5e","repo":"GraphiteEditor/Graphite","slug":"boolean-node-does-not-exist","errorCode":null,"errorMessage":"Boolean node does not exist","messagePattern":"Boolean node does not exist","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"editor/src/messages/portfolio/document/graph_operation/utility_types.rs","lineNumber":87,"sourceCode":"\t}\n\n\t/// Creates an artboard as the primary export for the document network.\n\tpub fn create_artboard(&mut self, new_id: NodeId, location: DVec2, dimensions: DVec2, background: Color, clip: bool) -> LayerNodeIdentifier {\n\t\tlet artboard_node_template = resolve_network_node_type(\"Artboard\").expect(\"Node\").node_template_input_override([\n\t\t\tSome(NodeInput::type_default(list!(Artboard), true)),\n\t\t\tSome(NodeInput::type_default(list!(Graphic), true)),\n\t\t\tSome(NodeInput::value(TaggedValue::DVec2(location), false)),\n\t\t\tSome(NodeInput::value(TaggedValue::DVec2(dimensions), false)),\n\t\t\tSome(NodeInput::value(TaggedValue::Color(background), false)),\n\t\t\tSome(NodeInput::value(TaggedValue::Bool(clip), false)),\n\t\t]);\n\t\tself.network_interface.insert_node(new_id, artboard_node_template, &[]);\n\t\tLayerNodeIdentifier::new(new_id, self.network_interface)\n\t}\n\n\tpub fn insert_boolean_data(&mut self, operation: graphene_std::vector::misc::BooleanOperation, layer: LayerNodeIdentifier) {\n\t\tlet boolean = resolve_proto_node_type(graphene_std::path_bool_nodes::boolean_operation::IDENTIFIER)\n\t\t\t.expect(\"Boolean node does not exist\")\n\t\t\t.node_template_input_override([\n\t\t\t\tSome(NodeInput::type_default(list!(Graphic), true)),\n\t\t\t\tSome(NodeInput::value(TaggedValue::BooleanOperation(operation), false)),\n\t\t\t]);\n\n\t\tlet boolean_id = NodeId::new();\n\t\tself.network_interface.insert_node(boolean_id, boolean, &[]);\n\t\tself.network_interface.move_node_to_chain_start(&boolean_id, layer, &[], self.import);\n\t}\n\n\tpub fn insert_blend_data(&mut self, layer: LayerNodeIdentifier, count: f64) -> NodeId {\n\t\tlet blend = resolve_network_node_type(\"Blend\")\n\t\t\t.expect(\"Blend node does not exist\")\n\t\t\t.node_template_input_override([Some(NodeInput::type_default(list!(Graphic), true)), Some(NodeInput::value(TaggedValue::F64(count), false))]);\n\n\t\tlet blend_id = NodeId::new();\n\t\tself.network_interface.insert_node(blend_id, blend, &[]);\n\t\tself.network_interface.move_node_to_chain_start(&blend_id, layer, &[], self.import);","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/editor/src/messages/portfolio/document/graph_operation/utility_types.rs#L69-L105","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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`."],"exampleFix":"// before\nlet boolean = resolve_proto_node_type(graphene_std::path_bool_nodes::boolean_operation::IDENTIFIER)\n    .expect(\"Boolean node does not exist\")\n    .node_template_input_override([\n\n// after\nlet Some(boolean_def) = resolve_proto_node_type(graphene_std::path_bool_nodes::boolean_operation::IDENTIFIER) else {\n    log::error!(\"Boolean Operation proto node not registered; skipping boolean insert\");\n    return;\n};\nlet boolean = boolean_def.node_template_input_override([","handlingStrategy":"validation","validationCode":"// Before applying a boolean operation:\nif document_node_definitions::resolve_proto_node_type(graphene_std::path_bool_nodes::boolean_operation::IDENTIFIER).is_none() {\n    log::error!(\"Boolean Operation node not registered; command unavailable\");\n    return;\n}","typeGuard":"fn boolean_operation_registered() -> bool {\n    document_node_definitions::resolve_proto_node_type(graphene_std::path_bool_nodes::boolean_operation::IDENTIFIER).is_some()\n}","tryCatchPattern":"// Rust has no try/catch; handle the Option before mutating the graph:\nlet Some(bool_def) = resolve_proto_node_type(graphene_std::path_bool_nodes::boolean_operation::IDENTIFIER) else {\n    log::error!(\"Boolean node missing\");\n    return;\n};","preventionTips":["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"],"tags":["rust","panic","expect","node-registry","proto-node","boolean-operation","graphite"],"backgroundTag":"node-definition-not-found","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}