{"record":{"id":"fe06fc69e96c5254","repo":"GraphiteEditor/Graphite","slug":"text-node-does-not-exist","errorCode":null,"errorMessage":"Text node does not exist","messagePattern":"Text node does not exist","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"editor/src/messages/portfolio/document/graph_operation/utility_types.rs","lineNumber":192,"sourceCode":"\t\t\tlet stroke_id = NodeId::new();\n\t\t\tself.network_interface.insert_node(stroke_id, stroke, &[]);\n\t\t\tself.network_interface.move_node_to_chain_start(&stroke_id, layer, &[], self.import);\n\t\t}\n\n\t\tif include_fill {\n\t\t\tlet fill = resolve_proto_node_type(graphene_std::vector_nodes::fill::IDENTIFIER)\n\t\t\t\t.expect(\"Fill node does not exist\")\n\t\t\t\t.default_node_template();\n\t\t\tlet fill_id = NodeId::new();\n\t\t\tself.network_interface.insert_node(fill_id, fill, &[]);\n\t\t\tself.network_interface.move_node_to_chain_start(&fill_id, layer, &[], self.import);\n\t\t}\n\t}\n\n\tpub fn insert_text(&mut self, text: String, font: Font, typesetting: TypesettingConfig, layer: LayerNodeIdentifier) {\n\t\tlet font_resource_id = ResourceId::new();\n\t\tlet text = resolve_proto_node_type(graphene_std::text::text::IDENTIFIER)\n\t\t\t.expect(\"Text node does not exist\")\n\t\t\t.node_template_input_override([\n\t\t\t\tSome(NodeInput::value(TaggedValue::None, false)),\n\t\t\t\tSome(NodeInput::value(TaggedValue::String(text), false)),\n\t\t\t\tSome(NodeInput::value(TaggedValue::Resource(font_resource_id), false)),\n\t\t\t\tSome(NodeInput::value(TaggedValue::F64(typesetting.font_size), false)),\n\t\t\t\tSome(NodeInput::value(TaggedValue::F64(typesetting.line_height_ratio), false)),\n\t\t\t\tSome(NodeInput::value(TaggedValue::F64(typesetting.letter_spacing), false)),\n\t\t\t\tSome(NodeInput::value(TaggedValue::F64(typesetting.letter_tilt), false)),\n\t\t\t\tSome(NodeInput::value(TaggedValue::Bool(typesetting.max_width.is_some()), false)),\n\t\t\t\tSome(NodeInput::value(TaggedValue::F64(typesetting.max_width.unwrap_or(100.)), false)),\n\t\t\t\tSome(NodeInput::value(TaggedValue::Bool(typesetting.max_height.is_some()), false)),\n\t\t\t\tSome(NodeInput::value(TaggedValue::F64(typesetting.max_height.unwrap_or(100.)), false)),\n\t\t\t\tSome(NodeInput::value(TaggedValue::TextAlign(typesetting.align), false)),\n\t\t\t]);\n\t\tlet text_to_vector = resolve_proto_node_type(graphene_std::text::text_to_vector::IDENTIFIER)\n\t\t\t.expect(\"Text to Vector node does not exist\")\n\t\t\t.default_node_template();\n\t\tlet transform = resolve_proto_node_type(graphene_std::transform_nodes::transform::IDENTIFIER)","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/editor/src/messages/portfolio/document/graph_operation/utility_types.rs#L174-L210","documentation":"Panics when `resolve_proto_node_type(graphene_std::text::text::IDENTIFIER)` returns `None` in `insert_text`, which builds the text node's input override list (string content, font resource, font size, line height, letter spacing/tilt, max width/height flags and values, alignment). The text proto-node definition must be registered in the static registry; the expect is a registry-presence assertion.","triggerScenarios":"Creating a text layer (text tool activation, text insertion flows) calls `insert_text`. Fires when the `graphene_std::text::text` IDENTIFIER is missing from `DOCUMENT_NODE_TYPES` — the text node moved crates/modules, its IDENTIFIER changed, or its definition is not registered in this build.","commonSituations":"Text-node refactors in `graphene_std::text`; renaming identifiers; font/text subsystem changes that forget the editor-side registry entry.","solutions":["Verify the registry resolves `graphene_std::text::text::IDENTIFIER`.","Repair identifier/registry drift on the side that changed.","Handle `None` with a logged early return before creating any nodes or font resources.","Add this identifier to automated registry-completeness checks."],"exampleFix":"// before\nlet text = resolve_proto_node_type(graphene_std::text::text::IDENTIFIER)\n    .expect(\"Text node does not exist\")\n    .node_template_input_override([\n\n// after\nlet Some(text_def) = resolve_proto_node_type(graphene_std::text::text::IDENTIFIER) else {\n    log::error!(\"Text proto node not registered; cannot create text layer\");\n    return;\n};\nlet text = text_def.node_template_input_override([","handlingStrategy":"validation","validationCode":"// Before creating a text layer:\nif document_node_definitions::resolve_proto_node_type(graphene_std::text::text::IDENTIFIER).is_none() {\n    log::error!(\"Text node not registered; text tool unavailable\");\n    return;\n}","typeGuard":"fn text_node_registered() -> bool {\n    document_node_definitions::resolve_proto_node_type(graphene_std::text::text::IDENTIFIER).is_some()\n}","tryCatchPattern":"// Rust has no try/catch; branch on the Option before creating any nodes or font resources:\nlet Some(text_def) = resolve_proto_node_type(graphene_std::text::text::IDENTIFIER) else {\n    log::error!(\"Text node missing; aborting text layer creation\");\n    return;\n};","preventionTips":["Resolve all four text-chain definitions up front before inserting any node","Include text identifiers in registry-completeness tests","Synchronize graphene_std::text renames with the registry","Use let-else over expect"],"tags":["rust","panic","expect","node-registry","proto-node","text-node","typography","graphite"],"backgroundTag":"node-definition-not-found","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}