GraphiteEditor/Graphite · error
Origins to Polyline node does not exist
Error message
Origins to Polyline node does not exist
What it means
Panics when the string lookup `resolve_network_node_type("Origins to Polyline")` returns `None` inside `insert_control_path_data`. This helper builds a `Origins to Polyline -> Auto-Tangents -> Path` chain when constructing a control path for a layer; the definition must exist in `DOCUMENT_NODE_TYPES` under the exact key `"Origins to Polyline"`. The expect is a static registry-presence assertion.
Source
Thrown at editor/src/messages/portfolio/document/graph_operation/utility_types.rs:126
}
pub fn insert_morph_data(&mut self, layer: LayerNodeIdentifier) -> NodeId {
let morph = resolve_proto_node_type(graphene_std::vector::morph::IDENTIFIER)
.expect("Morph node does not exist")
.node_template_input_override([Some(NodeInput::type_default(list!(Graphic), true)), Some(NodeInput::value(TaggedValue::F64(0.5), false))]);
let morph_id = NodeId::new();
self.network_interface.insert_node(morph_id, morph, &[]);
self.network_interface.move_node_to_chain_start(&morph_id, layer, &[], self.import);
morph_id
}
/// Returns the Path node ID (the node closest to the layer's merge node in the chain).
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);View on GitHub (pinned to c507b35645)
Solutions
- Grep `DOCUMENT_NODE_TYPES` for the exact string `"Origins to Polyline"`; re-add or fix the key if absent/renamed.
- If the node was renamed, update this call site or register an alias.
- Convert the `expect` into `Option` handling that logs and returns before inserting nodes.
- Prefer proto-node IDENTIFIER constants over display-name strings where possible.
Example fix
// before
let origins_to_polyline = resolve_network_node_type("Origins to Polyline")
.expect("Origins to Polyline node does not exist")
.default_node_template();
// after
let Some(otp_def) = resolve_network_node_type("Origins to Polyline") else {
log::error!("Origins to Polyline node not registered; aborting control path insert");
return NodeId::new();
};
let origins_to_polyline = otp_def.default_node_template(); Defensive patterns
Strategy: validation
Validate before calling
// Before building a control path:
if document_node_definitions::resolve_network_node_type("Origins to Polyline").is_none() {
log::error!("Origins to Polyline node not registered; control path unavailable");
return;
} Type guard
fn origins_to_polyline_available() -> bool {
document_node_definitions::resolve_network_node_type("Origins to Polyline").is_some()
} Try / catch
// Rust has no try/catch; branch on the Option:
let Some(otp_def) = resolve_network_node_type("Origins to Polyline") else {
log::error!("Origins to Polyline missing");
return;
}; Prevention
- Be extra careful with space-containing display-name keys — they are typo-prone
- Migrate string lookups to IDENTIFIER constants where an equivalent proto node exists
- Add exact-string registry tests for every display-name key used in code
- Alias renamed keys during transitions
When it happens
Trigger: Any tool path that creates a control path (e.g. momentum/origin-based path editing flows) calls `insert_control_path_data`. Fires when the `"Origins to Polyline"` key is missing — renamed display name, dropped registry entry, or typo in the string.
Common situations: Display-name-driven refactors (this lookup keys on a human-readable name containing spaces, so it is especially typo-prone); rebase drops; renaming the node in the properties panel without an alias.
Related errors
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/b0c61135c90a2808.
Report an issue: GitHub.