{"record":{"id":"f419954705c42298","repo":"GraphiteEditor/Graphite","slug":"blend-node-does-not-exist","errorCode":null,"errorMessage":"Blend node does not exist","messagePattern":"Blend node does not exist","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"editor/src/messages/portfolio/document/graph_operation/utility_types.rs","lineNumber":100,"sourceCode":"\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);\n\n\t\tblend_id\n\t}\n\n\tpub fn insert_morph_data(&mut self, layer: LayerNodeIdentifier) -> NodeId {\n\t\tlet morph = resolve_proto_node_type(graphene_std::vector::morph::IDENTIFIER)\n\t\t\t.expect(\"Morph node does not exist\")\n\t\t\t.node_template_input_override([Some(NodeInput::type_default(list!(Graphic), true)), Some(NodeInput::value(TaggedValue::F64(0.5), false))]);\n\n\t\tlet morph_id = NodeId::new();\n\t\tself.network_interface.insert_node(morph_id, morph, &[]);\n\t\tself.network_interface.move_node_to_chain_start(&morph_id, layer, &[], self.import);\n","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/editor/src/messages/portfolio/document/graph_operation/utility_types.rs#L82-L118","documentation":"Panics when the string lookup `resolve_network_node_type(\"Blend\")` returns `None` in `insert_blend_data`. The Blend node (step-count blend between shapes) is inserted at the chain start of a layer; the definition must exist in `DOCUMENT_NODE_TYPES` under exactly `\"Blend\"`. This is a static-invariant expect — it cannot fire unless the registry and this call site disagree on the key.","triggerScenarios":"Running the Blend operation on layers (`insert_blend_data` with a step count). Fires when the `\"Blend\"` key is missing from `DOCUMENT_NODE_TYPES`: renamed key/typo, deleted definition, or feature-gated registry entry.","commonSituations":"Registry refactors that rename display-name keys; merging branches where one side removed or renamed Blend; typos introduced when call sites are hand-edited from `\"Blend\"` to a new name.","solutions":["Verify the `\"Blend\"` key exists in `DOCUMENT_NODE_TYPES` and its definition is intact.","Align the string here with the actual registry key (or add an alias) if the node was renamed.","Replace the expect with `Option` handling that logs and returns `NodeId::new()`-free early exit (return before inserting anything).","Centralize these magic strings as constants shared with the registry definition."],"exampleFix":"// before\nlet blend = resolve_network_node_type(\"Blend\")\n    .expect(\"Blend node does not exist\")\n    .node_template_input_override([...]);\n\n// after\nlet Some(blend_def) = resolve_network_node_type(\"Blend\") else {\n    log::error!(\"Blend node definition not registered; aborting blend insert\");\n    return NodeId::new(); // caller must treat this as failure; better: return Option<NodeId>\n};\nlet blend = blend_def.node_template_input_override([...]);","handlingStrategy":"validation","validationCode":"// Before the blend operation:\nif document_node_definitions::resolve_network_node_type(\"Blend\").is_none() {\n    log::error!(\"Blend node not registered; command unavailable\");\n    return;\n}","typeGuard":"fn blend_node_available() -> bool {\n    document_node_definitions::resolve_network_node_type(\"Blend\").is_some()\n}","tryCatchPattern":"// Rust has no try/catch; branch on the Option:\nlet Some(blend_def) = resolve_network_node_type(\"Blend\") else {\n    log::error!(\"Blend node missing\");\n    return;\n};","preventionTips":["Use shared constants instead of inline \"Blend\" strings","Test blend flows whenever the registry file changes","Alias old keys when renaming","Return Option<NodeId> from insert helpers so callers can handle failure"],"tags":["rust","panic","expect","node-registry","string-lookup","blend-node","graphite"],"backgroundTag":"node-definition-not-found","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}