unoplatform/uno · error · InvalidOperationException

Expected event to start with 'On'

Error message

Expected event to start with 'On'

What it means

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.

Source

Thrown at src/SourceGenerators/Uno.UI.SourceGenerators/ImplementedRoutedEvents/ImplementedRoutedEventsGenerator.cs:175

			}

			return false;
		}

		private void ProcessType(INamedTypeSymbol type)
		{
			if (!type.IsAbstract &&
				type.Is(_uiElementSymbol) &&
				type.DeclaringSyntaxReferences[0].GetSyntax() is TypeDeclarationSyntax typeDeclaration &&
				IsPartialChainOfTypes(typeDeclaration))
			{
				var builder = new StringBuilder("global::Uno.UI.Xaml.RoutedEventFlag.None");

				foreach (var @event in _events)
				{
					if (!@event.Key.StartsWith("On", StringComparison.Ordinal))
					{
						throw new InvalidOperationException("Expected event to start with 'On'");
					}

					if (IsEventOverrideImplemented(type, @event.Key, @event.Value))
					{
						builder.Append($" | global::Uno.UI.Xaml.RoutedEventFlag.{@event.Key.Substring("On".Length)}");
					}
				}

				GenerateCode(type, builder.ToString());
			}
		}

		private bool IsEventOverrideImplemented(INamedTypeSymbol type, string name, INamedTypeSymbol arg)
		{
			if (type.Equals(_uiElementSymbol, SymbolEqualityComparer.Default) ||
				type.Equals(_controlSymbol, SymbolEqualityComparer.Default))
			{
				return false;

View on GitHub (pinned to 0418340488)

Solutions

  1. Find the dictionary entry added to ImplementedRoutedEventsGenerator whose key does not start with 'On' and rename it to the On<EventName> convention.
  2. Ensure the corresponding RoutedEventFlag enum member exists for the suffix after 'On'.

Example fix

// before
_events.Add("LostFocus", routedEventArgs);
// after
_events.Add("OnLostFocus", routedEventArgs);
Defensive patterns

Strategy: validation

Validate before calling

// Internal generator test: every _events key must start with 'On'
foreach (var key in events.Keys)
    if (!key.StartsWith("On", StringComparison.Ordinal))
        throw new InvalidOperationException($"Event key '{key}' must start with 'On'.");

Prevention

When it happens

Trigger: A developer adds an entry to the _events dictionary without the required 'On' prefix when editing ImplementedRoutedEventsGenerator.cs.

Common situations: Editing the generator source itself; a bad merge that introduces a non-'On' event key.

Related errors


AI-assisted analysis of unoplatform/uno@0418340488 (2026-08-13). Data as JSON: /api/errors/c8cf7e0704636663. Report an issue: GitHub.