GraphiteEditor/Graphite · error

Text node does not exist

Error message

Text node does not exist

What it means

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.

Source

Thrown at editor/src/messages/portfolio/document/graph_operation/utility_types.rs:192

			let stroke_id = NodeId::new();
			self.network_interface.insert_node(stroke_id, stroke, &[]);
			self.network_interface.move_node_to_chain_start(&stroke_id, layer, &[], self.import);
		}

		if include_fill {
			let fill = resolve_proto_node_type(graphene_std::vector_nodes::fill::IDENTIFIER)
				.expect("Fill node does not exist")
				.default_node_template();
			let fill_id = NodeId::new();
			self.network_interface.insert_node(fill_id, fill, &[]);
			self.network_interface.move_node_to_chain_start(&fill_id, layer, &[], self.import);
		}
	}

	pub fn insert_text(&mut self, text: String, font: Font, typesetting: TypesettingConfig, layer: LayerNodeIdentifier) {
		let font_resource_id = ResourceId::new();
		let text = resolve_proto_node_type(graphene_std::text::text::IDENTIFIER)
			.expect("Text node does not exist")
			.node_template_input_override([
				Some(NodeInput::value(TaggedValue::None, false)),
				Some(NodeInput::value(TaggedValue::String(text), false)),
				Some(NodeInput::value(TaggedValue::Resource(font_resource_id), false)),
				Some(NodeInput::value(TaggedValue::F64(typesetting.font_size), false)),
				Some(NodeInput::value(TaggedValue::F64(typesetting.line_height_ratio), false)),
				Some(NodeInput::value(TaggedValue::F64(typesetting.letter_spacing), false)),
				Some(NodeInput::value(TaggedValue::F64(typesetting.letter_tilt), false)),
				Some(NodeInput::value(TaggedValue::Bool(typesetting.max_width.is_some()), false)),
				Some(NodeInput::value(TaggedValue::F64(typesetting.max_width.unwrap_or(100.)), false)),
				Some(NodeInput::value(TaggedValue::Bool(typesetting.max_height.is_some()), false)),
				Some(NodeInput::value(TaggedValue::F64(typesetting.max_height.unwrap_or(100.)), false)),
				Some(NodeInput::value(TaggedValue::TextAlign(typesetting.align), false)),
			]);
		let text_to_vector = resolve_proto_node_type(graphene_std::text::text_to_vector::IDENTIFIER)
			.expect("Text to Vector node does not exist")
			.default_node_template();
		let transform = resolve_proto_node_type(graphene_std::transform_nodes::transform::IDENTIFIER)

View on GitHub (pinned to c507b35645)

Solutions

  1. Verify the registry resolves `graphene_std::text::text::IDENTIFIER`.
  2. Repair identifier/registry drift on the side that changed.
  3. Handle `None` with a logged early return before creating any nodes or font resources.
  4. Add this identifier to automated registry-completeness checks.

Example fix

// before
let text = resolve_proto_node_type(graphene_std::text::text::IDENTIFIER)
    .expect("Text node does not exist")
    .node_template_input_override([

// after
let Some(text_def) = resolve_proto_node_type(graphene_std::text::text::IDENTIFIER) else {
    log::error!("Text proto node not registered; cannot create text layer");
    return;
};
let text = text_def.node_template_input_override([
Defensive patterns

Strategy: validation

Validate before calling

// Before creating a text layer:
if document_node_definitions::resolve_proto_node_type(graphene_std::text::text::IDENTIFIER).is_none() {
    log::error!("Text node not registered; text tool unavailable");
    return;
}

Type guard

fn text_node_registered() -> bool {
    document_node_definitions::resolve_proto_node_type(graphene_std::text::text::IDENTIFIER).is_some()
}

Try / catch

// Rust has no try/catch; branch on the Option before creating any nodes or font resources:
let Some(text_def) = resolve_proto_node_type(graphene_std::text::text::IDENTIFIER) else {
    log::error!("Text node missing; aborting text layer creation");
    return;
};

Prevention

When it happens

Trigger: 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.

Common situations: Text-node refactors in `graphene_std::text`; renaming identifiers; font/text subsystem changes that forget the editor-side registry entry.

Related errors


AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16). Data as JSON: /api/errors/fe06fc69e96c5254. Report an issue: GitHub.