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
- Delete or relocate the offending attribute — the error span points at it
- Put cfg/allow attributes on individual items inside the module instead of the module itself
- 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
- Keep only doc comments on the #[editor_commands] module
- Place cfg/allow attributes on items inside the module, never on the module itself
- When a new module-level attribute seems needed, check the macro's constraints first
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
- #[editor_commands] takes no arguments
- 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}
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/bc959bb7941bb54e.
Report an issue: GitHub.