{"record":{"id":"6e8853c0b5d7592e","repo":"GraphiteEditor/Graphite","slug":"expected-messagehandler-trait","errorCode":null,"errorMessage":"Expected MessageHandler trait","messagePattern":"Expected MessageHandler trait","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"proc-macros/src/message_handler_data_attr.rs","lineNumber":30,"sourceCode":"\tlet path = match &**self_ty {\n\t\tType::Path(path) => &path.path,\n\t\t_ => return Err(syn::Error::new(Span::call_site(), \"Expected impl implementation\")),\n\t};\n\n\tlet input_type = path.segments.last().map(|s| &s.ident).unwrap();\n\n\tlet handler_line_number = input_type.span().start().line;\n\n\t// Extract the message type from the trait path\n\tlet trait_path = match &impl_block.trait_ {\n\t\tSome((_, path, _)) => path,\n\t\tNone => return Err(syn::Error::new(Span::call_site(), \"Expected trait implementation\")),\n\t};\n\n\t// Get the trait generics (should be MessageHandler<M, C>)\n\tif let Some(segment) = trait_path.segments.last() {\n\t\tif segment.ident != \"MessageHandler\" {\n\t\t\treturn Err(syn::Error::new(segment.ident.span(), \"Expected MessageHandler trait\"));\n\t\t}\n\t\tif let syn::PathArguments::AngleBracketed(args) = &segment.arguments {\n\t\t\tif args.args.len() >= 2 {\n\t\t\t\t// Extract the message type (M) and context struct type (C) from the trait params\n\t\t\t\tlet message_type = &args.args[0];\n\t\t\t\tlet data_type = &args.args[1];\n\n\t\t\t\tlet impl_item = match data_type {\n\t\t\t\t\tsyn::GenericArgument::Type(t) => {\n\t\t\t\t\t\tmatch t {\n\t\t\t\t\t\t\tsyn::Type::Path(type_path) if !type_path.path.segments.is_empty() => {\n\t\t\t\t\t\t\t\t// Get just the base identifier (ToolMessageData) without generics\n\t\t\t\t\t\t\t\tlet type_name = &type_path.path.segments.first().unwrap().ident;\n\n\t\t\t\t\t\t\t\tlet handler_data_line_number = type_name.span().start().line;\n\n\t\t\t\t\t\t\t\tquote! {\n\t\t\t\t\t\t\t\t\t#input_item","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/proc-macros/src/message_handler_data_attr.rs#L12-L48","documentation":"The trait being implemented under `#[message_handler_data]` must literally end in a segment named `MessageHandler` (i.e. `MessageHandler<M, C>`). This error is raised when the last path segment of the trait is a different name, because the macro cannot pull the message and context types from its angle-bracketed arguments.","triggerScenarios":"Writing `#[message_handler_data] impl SomeOtherTrait for MyHandler { … }`, importing MessageHandler under an alias so the segment name differs, or using a re-exported/renamed trait path whose final segment is not exactly `MessageHandler`.","commonSituations":"Copy-pasting an impl block from another trait integration, trait aliases or wrapper traits added during a refactor, or namespaced paths like `handlers::MessageHandler` are fine only if the last segment still reads `MessageHandler`.","solutions":["Make the impl target the real trait: `impl MessageHandler<M, C> for MyHandler { … }`.","If you aliased the trait (`use x::MessageHandler as MH;`), use the original name in the impl so the segment matches.","Remove the attribute from impls of unrelated traits — they don't need message-handler registration."],"exampleFix":"// before\n#[message_handler_data]\nimpl SomeOtherTrait for BrushTool { ... }\n\n// after\n#[message_handler_data]\nimpl MessageHandler<BrushMessage, BrushToolMessageData> for BrushTool { ... }","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["End the trait path with exactly `MessageHandler` in annotated impls; avoid trait aliases in that position.","Keep unrelated trait impls unannotated."],"tags":["rust","proc-macro","message-handler","trait-name"],"backgroundTag":"proc-macro-input-validation","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}