{"record":{"id":"c8cf7e0704636663","repo":"unoplatform/uno","slug":"expected-event-to-start-with-on","errorCode":null,"errorMessage":"Expected event to start with 'On'","messagePattern":"Expected event to start with 'On'","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/SourceGenerators/Uno.UI.SourceGenerators/ImplementedRoutedEvents/ImplementedRoutedEventsGenerator.cs","lineNumber":175,"sourceCode":"\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\tprivate void ProcessType(INamedTypeSymbol type)\n\t\t{\n\t\t\tif (!type.IsAbstract &&\n\t\t\t\ttype.Is(_uiElementSymbol) &&\n\t\t\t\ttype.DeclaringSyntaxReferences[0].GetSyntax() is TypeDeclarationSyntax typeDeclaration &&\n\t\t\t\tIsPartialChainOfTypes(typeDeclaration))\n\t\t\t{\n\t\t\t\tvar builder = new StringBuilder(\"global::Uno.UI.Xaml.RoutedEventFlag.None\");\n\n\t\t\t\tforeach (var @event in _events)\n\t\t\t\t{\n\t\t\t\t\tif (!@event.Key.StartsWith(\"On\", StringComparison.Ordinal))\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow new InvalidOperationException(\"Expected event to start with 'On'\");\n\t\t\t\t\t}\n\n\t\t\t\t\tif (IsEventOverrideImplemented(type, @event.Key, @event.Value))\n\t\t\t\t\t{\n\t\t\t\t\t\tbuilder.Append($\" | global::Uno.UI.Xaml.RoutedEventFlag.{@event.Key.Substring(\"On\".Length)}\");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tGenerateCode(type, builder.ToString());\n\t\t\t}\n\t\t}\n\n\t\tprivate bool IsEventOverrideImplemented(INamedTypeSymbol type, string name, INamedTypeSymbol arg)\n\t\t{\n\t\t\tif (type.Equals(_uiElementSymbol, SymbolEqualityComparer.Default) ||\n\t\t\t\ttype.Equals(_controlSymbol, SymbolEqualityComparer.Default))\n\t\t\t{\n\t\t\t\treturn false;","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/unoplatform/uno/blob/04183404888ea21b4e5bfa3493e8d5f15e972c3a/src/SourceGenerators/Uno.UI.SourceGenerators/ImplementedRoutedEvents/ImplementedRoutedEventsGenerator.cs#L157-L193","documentation":"ProcessType iterates the generator's internal _events dictionary and asserts every key begins with 'On' (OnLostFocus, OnGotFocus, OnBringIntoViewRequested) so it can derive the RoutedEventFlag name by stripping the prefix. This is an internal invariant on the hardcoded dictionary, not a user-configurable input.","triggerScenarios":"A developer adds an entry to the _events dictionary without the required 'On' prefix when editing ImplementedRoutedEventsGenerator.cs.","commonSituations":"Editing the generator source itself; a bad merge that introduces a non-'On' event key.","solutions":["Find the dictionary entry added to ImplementedRoutedEventsGenerator whose key does not start with 'On' and rename it to the On<EventName> convention.","Ensure the corresponding RoutedEventFlag enum member exists for the suffix after 'On'."],"exampleFix":"// before\n_events.Add(\"LostFocus\", routedEventArgs);\n// after\n_events.Add(\"OnLostFocus\", routedEventArgs);","handlingStrategy":"validation","validationCode":"// Internal generator test: every _events key must start with 'On'\nforeach (var key in events.Keys)\n    if (!key.StartsWith(\"On\", StringComparison.Ordinal))\n        throw new InvalidOperationException($\"Event key '{key}' must start with 'On'.\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When adding routed events to the generator dictionary, always use the On<EventName> convention.","Add a unit test asserting the 'On' prefix invariant on the dictionary."],"tags":["roslyn","source-generator","routed-events","invariant","internal"],"backgroundTag":null,"analyzedSha":"04183404888ea21b4e5bfa3493e8d5f15e972c3a","analyzedAt":"2026-08-13T21:08:11.651Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}