dotnet/maui · error · ArgumentException

uniqueName must not contain a .

Error message

uniqueName must not contain a .

What it means

ExportEffectAttribute rejects any uniqueName containing '.', because the runtime resolves effects via the 'ResolutionGroupName.Name' composite and an embedded dot would collide with that scheme or produce an ambiguous id. The constructor (ExportEffectAttribute.cs:22) does an ordinal IndexOf check and throws ArgumentException before storing the id.

Source

Thrown at src/Controls/src/Core/ExportEffectAttribute.cs:22

namespace Microsoft.Maui.Controls
{
#pragma warning disable CS1734 // XML comment on 'ExportEffectAttribute' has a paramref tag for 'effectType', but there is no parameter by that name
	/// <summary>Attribute that identifies a <see cref="Microsoft.Maui.Controls.Effect"/> with a unique identifier that can be used with <see cref="M:Microsoft.Maui.Controls.Effect.Resolve(System.String)"/> to locate an effect.</summary>
#pragma warning restore CS1734
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	public sealed class ExportEffectAttribute : Attribute
	{
		/// <summary>Creates a new <see cref="Microsoft.Maui.Controls.ExportEffectAttribute"/>.</summary>
		/// <param name="effectType">The type of the marked <see cref="Microsoft.Maui.Controls.Effect"/>.</param>
		/// <param name="uniqueName">A unique name for the <see cref="Microsoft.Maui.Controls.Effect"/>.</param>
		/// <remarks>Developers must supply a</remarks>
		public ExportEffectAttribute(
			[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type effectType,
			string uniqueName)
		{
			if (uniqueName.IndexOf(".", StringComparison.Ordinal) != -1)
				throw new ArgumentException("uniqueName must not contain a .");
			Type = effectType;
			Id = uniqueName;
		}

		internal string Id { get; private set; }

		[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
		internal Type Type { get; private set; }
	}
}

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Remove all '.' characters from the uniqueName argument, e.g. use "MyEffect" not "MyCompany.MyEffect".
  2. Keep the resolution group name on ExportEffect via the separate [assembly: ResolutionGroupName("MyCompany")] attribute; the group and the effect name are concatenated by the runtime.
  3. If you need namespacing for uniqueness, use camelCase or underscores ("MyCompany_MyEffect") rather than dots.
  4. Audit every ExportEffect assembly attribute for stray dots after bulk edits.

Example fix

// before
[assembly: ExportEffect(typeof(MyEffect), "Acme.MyEffect")]

// after
[assembly: ResolutionGroupName("Acme")]
[assembly: ExportEffect(typeof(MyEffect), "MyEffect")]
Defensive patterns

Strategy: validation

Validate before calling

if (uniqueName.Contains('.')) throw new ArgumentException("uniqueName must not contain '.'");

Prevention

When it happens

Trigger: Decorating an assembly with `[assembly: ExportEffect(typeof(MyEffect), "My.Group.Name")]` or any name containing a period. Also triggered by copy-paste from ExportCell/ExportHandler attributes whose naming conventions differ.

Common situations: Migrating from Xamarin.Forms where names were reused, auto-generating effect attributes from a script that joins segments with '.', or accidentally including a namespace prefix in the uniqueName.

Related errors


AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13). Data as JSON: /api/errors/62db34a53a865689. Report an issue: GitHub.