{"record":{"id":"b0c61135c90a2808","repo":"GraphiteEditor/Graphite","slug":"origins-to-polyline-node-does-not-exist","errorCode":null,"errorMessage":"Origins to Polyline node does not exist","messagePattern":"Origins to Polyline node does not exist","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"editor/src/messages/portfolio/document/graph_operation/utility_types.rs","lineNumber":126,"sourceCode":"\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\n\t\tmorph_id\n\t}\n\n\t/// Returns the Path node ID (the node closest to the layer's merge node in the chain).\n\tpub fn insert_control_path_data(&mut self, layer: LayerNodeIdentifier) -> NodeId {\n\t\t// Add Origins to Polyline node first (will be pushed deepest in the chain)\n\t\tlet origins_to_polyline = resolve_network_node_type(\"Origins to Polyline\")\n\t\t\t.expect(\"Origins to Polyline node does not exist\")\n\t\t\t.default_node_template();\n\t\tlet origins_to_polyline_id = NodeId::new();\n\t\tself.network_interface.insert_node(origins_to_polyline_id, origins_to_polyline, &[]);\n\t\tself.network_interface.move_node_to_chain_start(&origins_to_polyline_id, layer, &[], self.import);\n\n\t\t// Add Auto-Tangents node (between Origins to Polyline and Path), with spread=1 and preserve_existing=false\n\t\tlet auto_tangents = resolve_proto_node_type(graphene_std::vector::auto_tangents::IDENTIFIER)\n\t\t\t.expect(\"Auto-Tangents node does not exist\")\n\t\t\t.node_template_input_override([None, Some(NodeInput::value(TaggedValue::F64(1.), false)), Some(NodeInput::value(TaggedValue::Bool(false), false))]);\n\t\tlet auto_tangents_id = NodeId::new();\n\t\tself.network_interface.insert_node(auto_tangents_id, auto_tangents, &[]);\n\t\tself.network_interface.move_node_to_chain_start(&auto_tangents_id, layer, &[], self.import);\n\n\t\t// Add Path node to chain start (closest to the Merge node)\n\t\tlet path = resolve_network_node_type(\"Path\").expect(\"Path node does not exist\").default_node_template();\n\t\tlet path_id = NodeId::new();\n\t\tself.network_interface.insert_node(path_id, path, &[]);\n\t\tself.network_interface.move_node_to_chain_start(&path_id, layer, &[], self.import);","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/editor/src/messages/portfolio/document/graph_operation/utility_types.rs#L108-L144","documentation":"Panics when the string lookup `resolve_network_node_type(\"Origins to Polyline\")` returns `None` inside `insert_control_path_data`. This helper builds a `Origins to Polyline -> Auto-Tangents -> Path` chain when constructing a control path for a layer; the definition must exist in `DOCUMENT_NODE_TYPES` under the exact key `\"Origins to Polyline\"`. The expect is a static registry-presence assertion.","triggerScenarios":"Any tool path that creates a control path (e.g. momentum/origin-based path editing flows) calls `insert_control_path_data`. Fires when the `\"Origins to Polyline\"` key is missing — renamed display name, dropped registry entry, or typo in the string.","commonSituations":"Display-name-driven refactors (this lookup keys on a human-readable name containing spaces, so it is especially typo-prone); rebase drops; renaming the node in the properties panel without an alias.","solutions":["Grep `DOCUMENT_NODE_TYPES` for the exact string `\"Origins to Polyline\"`; re-add or fix the key if absent/renamed.","If the node was renamed, update this call site or register an alias.","Convert the `expect` into `Option` handling that logs and returns before inserting nodes.","Prefer proto-node IDENTIFIER constants over display-name strings where possible."],"exampleFix":"// before\nlet origins_to_polyline = resolve_network_node_type(\"Origins to Polyline\")\n    .expect(\"Origins to Polyline node does not exist\")\n    .default_node_template();\n\n// after\nlet Some(otp_def) = resolve_network_node_type(\"Origins to Polyline\") else {\n    log::error!(\"Origins to Polyline node not registered; aborting control path insert\");\n    return NodeId::new();\n};\nlet origins_to_polyline = otp_def.default_node_template();","handlingStrategy":"validation","validationCode":"// Before building a control path:\nif document_node_definitions::resolve_network_node_type(\"Origins to Polyline\").is_none() {\n    log::error!(\"Origins to Polyline node not registered; control path unavailable\");\n    return;\n}","typeGuard":"fn origins_to_polyline_available() -> bool {\n    document_node_definitions::resolve_network_node_type(\"Origins to Polyline\").is_some()\n}","tryCatchPattern":"// Rust has no try/catch; branch on the Option:\nlet Some(otp_def) = resolve_network_node_type(\"Origins to Polyline\") else {\n    log::error!(\"Origins to Polyline missing\");\n    return;\n};","preventionTips":["Be extra careful with space-containing display-name keys — they are typo-prone","Migrate string lookups to IDENTIFIER constants where an equivalent proto node exists","Add exact-string registry tests for every display-name key used in code","Alias renamed keys during transitions"],"tags":["rust","panic","expect","node-registry","string-lookup","origins-to-polyline","control-path","graphite"],"backgroundTag":"node-definition-not-found","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}