GraphiteEditor/Graphite · error · syn::Error
Validation error: {e}
Error message
Validation error:
{e} What it means
Emitted when validate_node_fn rejects a node function that parsed successfully — semantic rules rather than syntax. The validator set covers implementations for generics, primary-input exposure, min/max usage, slider bounds, Item<T> parameter pairing, element-wise structure, and ranked inputs. Most current validators report via proc-macro-error's emit_error! with their own messages, so this wrapper text is the hard-failure path of validate_node_fn.
Source
Thrown at node-graph/node-macro/src/parsing.rs:1029
}
fn parse_output(output: &ReturnType) -> syn::Result<Type> {
match output {
ReturnType::Default => Ok(syn::parse_quote!(())),
ReturnType::Type(_, ty) => Ok((**ty).clone()),
}
}
fn extract_attribute<'a>(attrs: &'a [Attribute], name: &str) -> Option<&'a Attribute> {
attrs.iter().find(|attr| attr.path().is_ident(name))
}
// Modify the new_node_fn function to use the code generation
pub fn new_node_fn(attr: TokenStream2, item: TokenStream2) -> syn::Result<TokenStream2> {
let crate_ident = CrateIdent::default();
let mut parsed_node = parse_node_fn(attr, item.clone()).map_err(|e| Error::new(e.span(), format!("Failed to parse node function:\n{e}")))?;
parsed_node.replace_impl_trait_in_input();
crate::validation::validate_node_fn(&parsed_node).map_err(|e| Error::new(e.span(), format!("Validation error:\n{e}")))?;
generate_node_code(&crate_ident, &parsed_node).map_err(|e| Error::new(e.span(), format!("Failed to generate node code:\n{e}")))
}
impl ParsedNodeFn {
/// The node's primary: the first argument (non-environment) field, whose declared shape classifies the node
/// as an element-wise kernel, aggregation, or generator. Returns the field with its index in `fields`.
pub(crate) fn primary_input_field(&self) -> Option<(usize, &ParsedField)> {
self.fields.iter().enumerate().find(|(_, field)| !field.is_environment())
}
pub fn replace_impl_trait_in_input(&mut self) {
if let Type::ImplTrait(impl_trait) = self.input.ty.clone() {
let ident = Ident::new("_Input", impl_trait.span());
let mut bounds = impl_trait.bounds;
bounds.push(parse_quote!('n));
self.fn_generics.push(GenericParam::Type(TypeParam {
attrs: Default::default(),
ident: ident.clone(),View on GitHub (pinned to c507b35645)
Solutions
- Read the validator text after the header — it names the rule and the offending parameter
- Give Item<T> parameters a ranked primary input (Item<T>, List<T>, or ListDyn), or drop the Item wrapper
- Add #[implementations(...)] for every generic parameter, or opt out with skip_impl when implementations are registered manually
- Check min/max and slider-bound attributes against their constraints
Example fix
// before: Item<T> parameter but an unranked primary input
#[node_macro::node(category("Color"))]
fn blend(base: f64, #[implementations(f32, f64)] each: Item<f64>) -> f64 { /* ... */ }
// after: make the primary input ranked so the frame matches
#[node_macro::node(category("Color"))]
fn blend(base: List<f64>, #[implementations(f32, f64)] each: Item<f64>) -> f64 { /* ... */ } Defensive patterns
Strategy: validation
Prevention
- Model new nodes on existing element-wise, aggregation, or generator nodes with the same shape
- Give Item<T> parameters a ranked primary input (Item<T>, List<T>, ListDyn)
- Declare #[implementations(...)] for every generic parameter up front, or use skip_impl deliberately
When it happens
Trigger: A parsed node whose shape violates the rules: an Item<T> parameter on a node whose primary input is not ranked (Item<T>, List<T>, or ListDyn); #[implementations(...)] on a ranked parameter containing non-bare element types; generic type parameters without implementations when skip_impl is not set; invalid min/max or slider-bound attribute combinations.
Common situations: Adding a per-element (Item<T>) parameter to a node whose primary input is a plain value; forgetting #[implementations(...)] on a newly introduced generic parameter; converting an aggregation node to a generator while leaving ranked parameters behind.
Related errors
- Failed to parse input type for #[implementation(...)]. Expec
- Expected `->` arrow after input type in #[implementations(..
- Failed to parse output type for #[implementation(...)]. Expe
- Failed to parse node_fn attributes: {e}
- Failed to parse implementations for argument '{name}': {e}
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/0bfdac08c42836d5.
Report an issue: GitHub.