{"record":{"id":"4b1174d95a7f95a8","repo":"GraphiteEditor/Graphite","slug":"spiral-node-can-t-be-found","errorCode":null,"errorMessage":"Spiral node can't be found","messagePattern":"Spiral node can't be found","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"editor/src/messages/tool/common_functionality/shapes/spiral_shape.rs","lineNumber":104,"sourceCode":"\tlet (spiral_type, start_angle, a, outer_radius, turns, _) = extract_spiral_parameters(layer, document)?;\n\tlet b = calculate_growth_factor(a, turns, outer_radius, spiral_type);\n\tlet theta = turns * theta + start_angle.to_radians();\n\n\tSome(viewport.transform_point2(spiral_point(theta, a, b, spiral_type)))\n}\n\n#[derive(Default)]\npub struct Spiral;\n\nimpl Spiral {\n\tpub fn create_node(spiral_type: SpiralType, turns: f64) -> NodeTemplate {\n\t\tlet inner_radius = match spiral_type {\n\t\t\tSpiralType::Archimedean => 0.,\n\t\t\tSpiralType::Logarithmic => 0.1,\n\t\t};\n\n\t\tlet identifier = DefinitionIdentifier::ProtoNode(graphene_std::vector::generator_nodes::spiral::IDENTIFIER);\n\t\tlet node_type = resolve_document_node_type(&identifier).expect(\"Spiral node can't be found\");\n\t\tnode_type.node_template_input_override([\n\t\t\tNone,\n\t\t\tSome(NodeInput::value(TaggedValue::SpiralType(spiral_type), false)),\n\t\t\tSome(NodeInput::value(TaggedValue::F64(turns), false)),\n\t\t\tSome(NodeInput::value(TaggedValue::F64(0.), false)),\n\t\t\tSome(NodeInput::value(TaggedValue::F64(inner_radius), false)),\n\t\t\tSome(NodeInput::value(TaggedValue::F64(0.1), false)),\n\t\t\tSome(NodeInput::value(TaggedValue::F64(90.), false)),\n\t\t])\n\t}\n\n\tpub fn update_shape(\n\t\tdocument: &DocumentMessageHandler,\n\t\tipp: &InputPreprocessorMessageHandler,\n\t\tviewport: &ViewportMessageHandler,\n\t\tlayer: LayerNodeIdentifier,\n\t\tshape_tool_data: &mut ShapeToolData,\n\t\tresponses: &mut VecDeque<Message>,","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/editor/src/messages/tool/common_functionality/shapes/spiral_shape.rs#L86-L122","documentation":"Spiral::create_node resolves the Spiral generator via DefinitionIdentifier::ProtoNode(graphene_std::vector::generator_nodes::spiral::IDENTIFIER) and resolve_document_node_type(...).expect(\"Spiral node can't be found\") (spiral_shape.rs:104). The resolver is a get on the static DOCUMENT_NODE_TYPES HashMap (document_node_definitions.rs:130/1484); None — hence the panic — means the Spiral node is unregistered under that identifier. It fires the first time the Spiral tool inserts its node (with the type/turns defaults computed just above).","triggerScenarios":"Drawing with the Spiral tool while generator_nodes::spiral::IDENTIFIER is absent from DOCUMENT_NODE_TYPES (renamed const, removed node, or edited registration list).","commonSituations":"Renaming/moving the spiral generator during refactors; Graphite upgrades re-namespacing generator nodes; feature-gated builds excluding spiral; stale 7-element override arrays after the node's inputs change (separate index panic at document_node_definitions.rs:1536).","solutions":["Confirm the spiral identifier is registered by checking DOCUMENT_NODE_TYPES (grep its string in document_node_definitions.rs)","Fix the identifier/registration mismatch and rebuild","Use let-else so the spiral tool logs and skips layer creation instead of panicking","Add Spiral to the cross-tool registry-drift test"],"exampleFix":"// before\nlet node_type = resolve_document_node_type(&identifier).expect(\"Spiral node can't be found\");\n// after\nlet Some(node_type) = resolve_document_node_type(&identifier) else {\n\tlog::error!(\"Spiral node definition missing from DOCUMENT_NODE_TYPES\");\n\treturn None;\n};","handlingStrategy":"validation","validationCode":"fn spiral_node_available() -> bool {\n\tdocument_node_definitions::resolve_document_node_type(&DefinitionIdentifier::ProtoNode(graphene_std::vector::generator_nodes::spiral::IDENTIFIER)).is_some()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Add Spiral to the shared registry-drift test covering all shape tools","Note the 7-element override array here — the longest among shape tools and most likely to break when Spiral's inputs change","Prefer graceful let-else handling in tool code; reserve expect for invariants the compiler cannot check but tests do"],"tags":["rust","graphite","panic","expect","node-registry","spiral-tool"],"backgroundTag":"node-definition-not-found","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}