{"record":{"id":"708d1b387dc83597","repo":"GraphiteEditor/Graphite","slug":"failed-to-create-merge-node","errorCode":null,"errorMessage":"Failed to create merge node","messagePattern":"Failed to create merge node","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"editor/src/messages/tool/common_functionality/graph_modification_utils.rs","lineNumber":80,"sourceCode":"\t\t});\n\t\tcurrent_and_other_layer_is_spline = true;\n\t}\n\n\t// Move the `second_layer` below the `first_layer` for positioning purposes\n\tlet Some(first_layer_parent) = first_layer.parent(document.metadata()) else { return };\n\tlet Some(first_layer_index) = first_layer_parent.children(document.metadata()).position(|child| child == first_layer) else {\n\t\treturn;\n\t};\n\tresponses.add(NodeGraphMessage::MoveLayerToStack {\n\t\tlayer: second_layer,\n\t\tparent: first_layer_parent,\n\t\tinsert_index: first_layer_index + 1,\n\t});\n\n\t// Merge the inputs of the two layers\n\tlet merge_node_id = NodeId::new();\n\tlet merge_node = document_node_definitions::resolve_network_node_type(\"Merge\")\n\t\t.expect(\"Failed to create merge node\")\n\t\t.default_node_template();\n\tresponses.add(NodeGraphMessage::InsertNode {\n\t\tnode_id: merge_node_id,\n\t\tnode_template: Box::new(merge_node),\n\t});\n\tresponses.add(NodeGraphMessage::SetToNodeOrLayer {\n\t\tnode_id: merge_node_id,\n\t\tis_layer: false,\n\t});\n\tresponses.add(NodeGraphMessage::MoveNodeToChainStart {\n\t\tnode_id: merge_node_id,\n\t\tparent: first_layer,\n\t});\n\tresponses.add(NodeGraphMessage::ConnectUpstreamOutputToInput {\n\t\tdownstream_input: InputConnector::layer_secondary_input(second_layer.to_node()),\n\t\tinput_connector: InputConnector::layer_secondary_input(merge_node_id),\n\t});\n\tresponses.add(NodeGraphMessage::DeleteNodes {","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/editor/src/messages/tool/common_functionality/graph_modification_utils.rs#L62-L98","documentation":"When merging two layers, graph_modification_utils resolves the built-in 'Merge' node via document_node_definitions::resolve_network_node_type(\"Merge\") and expects it to exist. The lookup is a hashmap access on DOCUMENT_NODE_TYPES keyed by DefinitionIdentifier::Network(\"Merge\"); it returns None when the registry does not contain that identifier. Since the string is a compile-time constant referencing a built-in node, this panic means the registry and this call site drifted - the node was renamed, moved behind a feature flag, or the registry was not populated in this build.","triggerScenarios":"Invoking the layer-merge flow after 'Merge' was renamed in document_node_definitions.rs, its identifier string changed, or a build configuration excluded it from DOCUMENT_NODE_TYPES.","commonSituations":"Node registry refactors/renames without grepping for string call sites; splitting node definitions across crates/features so a target build lacks the Merge network node.","solutions":["Keep the identifier in sync: grep for \\\"Merge\\\" across the repo when renaming the node definition","Handle the None case by logging a clear 'node definition missing' error and aborting the merge transaction instead of panicking","Add a unit test that resolves every identifier used by graph_modification_utils so drift fails CI, not users"],"exampleFix":"// before\nlet merge_node = document_node_definitions::resolve_network_node_type(\"Merge\")\n\t.expect(\"Failed to create merge node\")\n\t.default_node_template();\n\n// after\nlet Some(merge_definition) = document_node_definitions::resolve_network_node_type(\"Merge\") else {\n\tlog::error!(\"Merge node definition missing from registry\");\n\treturn;\n};\nlet merge_node = merge_definition.default_node_template();","handlingStrategy":"validation","validationCode":"let Some(merge_definition) = document_node_definitions::resolve_network_node_type(\"Merge\") else {\n\tlog::error!(\"'Merge' node definition missing from registry\");\n\treturn;\n};","typeGuard":"fn node_type_registered(identifier: &str) -> bool {\n\tdocument_node_definitions::resolve_network_node_type(identifier).is_some()\n}","tryCatchPattern":null,"preventionTips":["Grep for the identifier string whenever renaming a built-in node definition","Resolve node types at the start of a multi-insert flow and abort before mutating the graph if any is missing","Add a CI test resolving every identifier referenced from tool code"],"tags":["rust","node-registry","layer-merge","lookup-miss","panic"],"backgroundTag":"node-definition-not-found","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}