GraphiteEditor/Graphite · error
Path node does not exist
Error message
Path node does not exist
What it means
Panics when `resolve_network_node_type("Path")` returns `None` at the end of `insert_control_path_data` (the Path node is added chain-start, closest to the layer's Merge node). The `"Path"` network-node definition must exist in the static registry; this expect asserts its presence. Because Path is one of the most fundamental node types, hitting this panic indicates wholesale registry breakage rather than an isolated rename.
Source
Thrown at editor/src/messages/portfolio/document/graph_operation/utility_types.rs:141
pub fn insert_control_path_data(&mut self, layer: LayerNodeIdentifier) -> NodeId {
// Add Origins to Polyline node first (will be pushed deepest in the chain)
let origins_to_polyline = resolve_network_node_type("Origins to Polyline")
.expect("Origins to Polyline node does not exist")
.default_node_template();
let origins_to_polyline_id = NodeId::new();
self.network_interface.insert_node(origins_to_polyline_id, origins_to_polyline, &[]);
self.network_interface.move_node_to_chain_start(&origins_to_polyline_id, layer, &[], self.import);
// Add Auto-Tangents node (between Origins to Polyline and Path), with spread=1 and preserve_existing=false
let auto_tangents = resolve_proto_node_type(graphene_std::vector::auto_tangents::IDENTIFIER)
.expect("Auto-Tangents node does not exist")
.node_template_input_override([None, Some(NodeInput::value(TaggedValue::F64(1.), false)), Some(NodeInput::value(TaggedValue::Bool(false), false))]);
let auto_tangents_id = NodeId::new();
self.network_interface.insert_node(auto_tangents_id, auto_tangents, &[]);
self.network_interface.move_node_to_chain_start(&auto_tangents_id, layer, &[], self.import);
// Add Path node to chain start (closest to the Merge node)
let path = resolve_network_node_type("Path").expect("Path node does not exist").default_node_template();
let path_id = NodeId::new();
self.network_interface.insert_node(path_id, path, &[]);
self.network_interface.move_node_to_chain_start(&path_id, layer, &[], self.import);
path_id
}
pub fn insert_vector(&mut self, subpaths: Vec<Subpath<PointId>>, layer: LayerNodeIdentifier, include_transform: bool, include_fill: bool, include_stroke: bool) {
// Build a VectorModification that reproduces the geometry (same format the Pen tool uses)
let vector = Vector::from_subpaths(subpaths, true);
let modification = Box::new(VectorModification::create_from_vector(&vector));
let shape = resolve_network_node_type("Path")
.expect("Path node does not exist")
.node_template_input_override([None, Some(NodeInput::value(TaggedValue::VectorModification(modification), false))]);
let shape_id = NodeId::new();
self.network_interface.insert_node(shape_id, shape, &[]);
self.network_interface.move_node_to_chain_start(&shape_id, layer, &[], self.import);View on GitHub (pinned to c507b35645)
Solutions
- Check that `"Path"` exists in `DOCUMENT_NODE_TYPES`; restore the entry if missing.
- Align the string with the registry key if the node was renamed (and audit the other `"Path"` call sites in this file).
- Replace the expect with logged `Option` handling, aborting the control-path insert on `None`.
- Add a smoke test that resolves every bare string used in `utility_types.rs`.
Example fix
// before
let path = resolve_network_node_type("Path").expect("Path node does not exist").default_node_template();
// after
let Some(path_def) = resolve_network_node_type("Path") else {
log::error!("Path node definition not registered; aborting control path insert");
return NodeId::new();
};
let path = path_def.default_node_template(); Defensive patterns
Strategy: validation
Validate before calling
// Before building a control path:
if document_node_definitions::resolve_network_node_type("Path").is_none() {
log::error!("Path node not registered; control path unavailable");
return;
} Type guard
fn path_node_available() -> bool {
document_node_definitions::resolve_network_node_type("Path").is_some()
} Try / catch
// Rust has no try/catch; branch on the Option:
let Some(path_def) = resolve_network_node_type("Path") else {
log::error!("Path node missing");
return;
}; Prevention
- Treat the Path key as core infrastructure — smoke test it in every CI run
- Extract one shared constant for "Path" and use it at all call sites
- Audit duplicated string keys after any definitions-file refactor
- Alias renamed keys instead of breaking lookups
When it happens
Trigger: Creating a control path for a layer. Fires when the `"Path"` key is missing from `DOCUMENT_NODE_TYPES` — e.g. the registry-generation macro broke, the entry was renamed, or a build config excluded core definitions.
Common situations: Major refactors of `document_node_definitions.rs`; rebase conflicts that silently drop entries; typos when the key string is duplicated at many call sites (this is one of several `"Path"` lookups in the file).
Related errors
- Origins to Polyline node does not exist
- Merge node
- Node
- Blend node does not exist
- Auto-Tangents node does not exist
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/1e1a65c4a4b99b1b.
Report an issue: GitHub.