{"record":{"id":"b7fe5921381c8e13","repo":"GraphiteEditor/Graphite","slug":"text-to-vector-node-does-not-exist","errorCode":null,"errorMessage":"Text to Vector node does not exist","messagePattern":"Text to Vector node does not exist","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"editor/src/messages/portfolio/document/graph_operation/utility_types.rs","lineNumber":208,"sourceCode":"\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)\n\t\t\t.expect(\"Transform node does not exist\")\n\t\t\t.default_node_template();\n\t\tlet fill = resolve_proto_node_type(graphene_std::vector_nodes::fill::IDENTIFIER)\n\t\t\t.expect(\"Fill node does not exist\")\n\t\t\t.default_node_template();\n\n\t\t// Build the chain `Text -> Text to Vector -> Transform -> Fill -> layer`\n\t\tlet text_id = NodeId::new();\n\t\tself.network_interface.insert_node(text_id, text, &[]);\n\t\tself.network_interface.move_node_to_chain_start(&text_id, layer, &[], self.import);\n\n\t\tself.responses.add(DocumentMessage::Resource(ResourceMessage::AddFont { resource_id: font_resource_id, font }));\n\n\t\tlet text_to_vector_id = NodeId::new();\n\t\tself.network_interface.insert_node(text_to_vector_id, text_to_vector, &[]);\n\t\tself.network_interface.move_node_to_chain_start(&text_to_vector_id, layer, &[], self.import);","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/editor/src/messages/portfolio/document/graph_operation/utility_types.rs#L190-L226","documentation":"Panics when `resolve_proto_node_type(graphene_std::text::text_to_vector::IDENTIFIER)` returns `None` in `insert_text`. Every text layer is built as the chain `Text -> Text to Vector -> Transform -> Fill -> layer`; the Text to Vector proto node rasterizes/converts the run layout into vector geometry. The expect asserts its definition exists in the static `DOCUMENT_NODE_TYPES` registry.","triggerScenarios":"Creating a text layer. Fires when the `text_to_vector` IDENTIFIER is absent from the registry — the node was renamed or moved within `graphene_std::text`, or its definition entry was dropped.","commonSituations":"Text subsystem refactors; identifier renames; registry omissions when nodes are added or merged.","solutions":["Confirm the registry entry for `text_to_vector` exists and matches the current IDENTIFIER constant.","Fix the drift: restore the constant's value or re-add the definition.","Handle `None` with a logged early return so no partial text chain is inserted.","Cover this identifier in registry-completeness tests."],"exampleFix":"// before\nlet text_to_vector = resolve_proto_node_type(graphene_std::text::text_to_vector::IDENTIFIER)\n    .expect(\"Text to Vector node does not exist\")\n    .default_node_template();\n\n// after\nlet Some(text_to_vector) = resolve_proto_node_type(graphene_std::text::text_to_vector::IDENTIFIER).map(|d| d.default_node_template()) else {\n    log::error!(\"Text to Vector proto node not registered; cannot create text layer\");\n    return;\n};","handlingStrategy":"validation","validationCode":"// Before creating a text layer:\nif document_node_definitions::resolve_proto_node_type(graphene_std::text::text_to_vector::IDENTIFIER).is_none() {\n    log::error!(\"Text to Vector node not registered; text tool unavailable\");\n    return;\n}","typeGuard":"fn text_to_vector_registered() -> bool {\n    document_node_definitions::resolve_proto_node_type(graphene_std::text::text_to_vector::IDENTIFIER).is_some()\n}","tryCatchPattern":"// Rust has no try/catch; branch on the Option:\nlet Some(ttv_def) = resolve_proto_node_type(graphene_std::text::text_to_vector::IDENTIFIER) else {\n    log::error!(\"Text to Vector missing; aborting text layer creation\");\n    return;\n};","preventionTips":["Batch-resolve the full text chain before mutating the graph","Include text_to_vector in registry tests","Register definitions atomically with node moves","Use let-else over expect"],"tags":["rust","panic","expect","node-registry","proto-node","text-to-vector","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"}