GraphiteEditor/Graphite · error

Color Value node does not exist

Error message

Color Value node does not exist

What it means

Panics when `resolve_proto_node_type(graphene_std::math_nodes::color_value::IDENTIFIER)` returns `None` in `insert_color_value`. Paint tools attach a Color Value node (fed into a layer's paint attachment input) to produce solid colors; the proto-node definition must be registered in the static `DOCUMENT_NODE_TYPES` registry. The expect is the standard registry-drift tripwire for the `color_value` identifier.

Source

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

		self.responses.add(DocumentMessage::Resource(ResourceMessage::AddFont { resource_id: font_resource_id, font }));

		let text_to_vector_id = NodeId::new();
		self.network_interface.insert_node(text_to_vector_id, text_to_vector, &[]);
		self.network_interface.move_node_to_chain_start(&text_to_vector_id, layer, &[], self.import);

		let transform_id = NodeId::new();
		self.network_interface.insert_node(transform_id, transform, &[]);
		self.network_interface.move_node_to_chain_start(&transform_id, layer, &[], self.import);

		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_color_value(&mut self, color: Color, layer: LayerNodeIdentifier, attachment_input: InputConnector) -> NodeId {
		let color_value = resolve_proto_node_type(graphene_std::math_nodes::color_value::IDENTIFIER)
			.expect("Color Value node does not exist")
			.node_template_input_override([Some(NodeInput::value(TaggedValue::None, false)), Some(NodeInput::value(TaggedValue::Color(color), false))]);

		let color_value_id = NodeId::new();
		self.network_interface.insert_node(color_value_id, color_value, &[]);
		self.start_paint_chain(&color_value_id, layer, attachment_input);

		color_value_id
	}

	/// Clear the whole-expanse paint one tool left on a layer so the other can start its own chain there.
	/// Severing at the attachment detaches the layer from whatever the walk stopped at, which is the only part a node
	/// the rest of the graph also draws from is subjected to, since such a node is never among those deleted.
	fn clear_paint_chain(&mut self, paint_chain: &ReplaceablePaintChain) {
		self.network_interface.disconnect_input(&paint_chain.attachment_input, &[]);

		if !paint_chain.nodes.is_empty() {
			self.network_interface.delete_nodes(paint_chain.nodes.clone(), false, &[]);
		}

View on GitHub (pinned to c507b35645)

Solutions

  1. Verify the registry contains a definition matching `graphene_std::math_nodes::color_value::IDENTIFIER`.
  2. Repair the drift: restore the IDENTIFIER value or re-add the registry entry.
  3. Handle `None` with a logged early return so the paint operation is skipped rather than crashing mid-stroke.
  4. Cover this identifier in registry-completeness tests.

Example fix

// before
let color_value = resolve_proto_node_type(graphene_std::math_nodes::color_value::IDENTIFIER)
    .expect("Color Value node does not exist")
    .node_template_input_override([...]);

// after
let Some(cv_def) = resolve_proto_node_type(graphene_std::math_nodes::color_value::IDENTIFIER) else {
    log::error!("Color Value proto node not registered; skipping paint insert");
    return NodeId::new();
};
let color_value = cv_def.node_template_input_override([...]);
Defensive patterns

Strategy: validation

Validate before calling

// Before a paint tool applies a color:
if document_node_definitions::resolve_proto_node_type(graphene_std::math_nodes::color_value::IDENTIFIER).is_none() {
    log::error!("Color Value node not registered; paint disabled");
    return;
}

Type guard

fn color_value_registered() -> bool {
    document_node_definitions::resolve_proto_node_type(graphene_std::math_nodes::color_value::IDENTIFIER).is_some()
}

Try / catch

// Rust has no try/catch; branch on the Option before starting the paint chain:
let Some(cv_def) = resolve_proto_node_type(graphene_std::math_nodes::color_value::IDENTIFIER) else {
    log::error!("Color Value missing; skipping paint");
    return;
};

Prevention

When it happens

Trigger: A tool applying a solid fill/stroke color to a layer via `insert_color_value` (then `start_paint_chain` wires it to the attachment input). Fires when the `math_nodes::color_value` IDENTIFIER is missing from the registry — node renamed, moved out of `math_nodes`, or definition never added.

Common situations: Refactors of `graphene_std::math_nodes`; renaming the Color Value node or its identifier; adding math nodes without registering their editor-side definitions.

Related errors


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