GraphiteEditor/Graphite · error · syn::Error

Failed to parse node function: {e}

Error message

Failed to parse node function:
{e}

What it means

The outermost wrapper in new_node_fn: it re-reports any failure from parse_node_fn — malformed #[node(...)] attributes, an annotated item that is not a valid function, or invalid parameter/output syntax — prefixed with this message at the original span. Expect nested text: "Failed to parse node function:\nFailed to parse node_fn attributes:\n...".

Source

Thrown at node-graph/node-macro/src/parsing.rs:1027

		"u8" | "u16" | "u32" | "u64" | "u128" | "usize" | "i8" | "i16" | "i32" | "i64" | "i128" | "isize"
	)
}

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 {

View on GitHub (pinned to c507b35645)

Solutions

  1. Read the indented inner message — it carries the actual cause and span; fix that first
  2. Ensure the annotated item is a plain fn declaration
  3. Re-run cargo check after fixing the inner error; this wrapper disappears along with it

Example fix

// before: node attribute on a struct
#[node_macro::node(category("Value"))]
struct MyNode;

// after: annotate a plain function
#[node_macro::node(category("Value"))]
fn my_node(input: f64) -> f64 { input }
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Applying #[node_macro::node(...)] to anything that is not a plain ItemFn (struct, impl block, trait method); Rust syntax errors inside the function signature or body; any of the inner attribute/parameter parse failures (errors 8–13) surfacing through this wrapper.

Common situations: Refactoring a node function into a struct-based node and leaving the attribute attached; large multi-error diffs where the actionable cause is the appended inner message, not this header.

Understand the failure class

Related errors


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