GraphiteEditor/Graphite · error · syn::Error

the #[editor_commands] module may not have other attributes

Error message

the #[editor_commands] module may not have other attributes

What it means

After the empty-attribute check, editor_commands_impl inspects the module's own attributes and permits only doc comments (#[doc ...]). Because the macro rewrites the module when generating editor command bindings, it cannot preserve arbitrary module-level attributes and rejects them with this spanned error.

Source

Thrown at proc-macros/src/editor_commands.rs:13

use convert_case::{Case, Casing};
use proc_macro2::TokenStream;
use quote::{quote, quote_spanned};
use syn::spanned::Spanned;
use syn::{Error, FnArg, Ident, Item, ItemFn, ItemMod, ItemUse, Pat, Visibility};

pub fn editor_commands_impl(attr: TokenStream, module: ItemMod) -> syn::Result<TokenStream> {
	if !attr.is_empty() {
		return Err(Error::new(attr.span(), "#[editor_commands] takes no arguments"));
	}
	for attr in &module.attrs {
		if !attr.path().is_ident("doc") {
			return Err(Error::new(attr.span(), "the #[editor_commands] module may not have other attributes"));
		}
	}
	let Some((_, items)) = module.content else {
		return Err(Error::new(module.mod_token.span, "#[editor_commands] requires a module with an inline body"));
	};

	let mut imports: Vec<ItemUse> = Vec::new();
	let mut functions: Vec<ItemFn> = Vec::new();
	for item in items {
		match item {
			Item::Use(import) => imports.push(import),
			Item::Fn(function) => functions.push(function),
			other => return Err(Error::new(other.span(), "only `use` imports and command functions may appear in an #[editor_commands] module")),
		}
	}

	let mut variants = TokenStream::new();
	let mut stubs = TokenStream::new();

View on GitHub (pinned to c507b35645)

Solutions

  1. Delete or relocate the offending attribute — the error span points at it
  2. Put cfg/allow attributes on individual items inside the module instead of the module itself
  3. Use doc comments (/// or #[doc]) freely; they are the only allowed module-level attributes

Example fix

// before
#[cfg(test)]
#[editor_commands]
mod commands { /* ... */ }

// after: move the cfg to items inside the module
#[editor_commands]
mod commands {
	#[cfg(test)]
	use crate::test_helpers::*;
	/* ... */
}
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Adding #[cfg(test)], #[allow(dead_code)], #[macro_use], or any other non-doc attribute above the #[editor_commands] module declaration.

Common situations: Trying to gate generated command bindings behind a feature flag; silencing lints at module level; IDE auto-inserting attributes during refactors.

Related errors


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