dotnet/maui · error · Exception

Error: Running UI tests with NativeAOT is only supported in

Error message

Error: Running UI tests with NativeAOT is only supported in Release configuration

What it means

Thrown in ExecuteBuildUITestApp as a hard guard: USE_NATIVE_AOT is enabled but the requested configuration is Debug. NativeAOT requires Release (NativeAOT does not support the Debug JIT profile and the publish path is Release-only), so this is an intentional configuration rejection before invoking DotNetBuild.

Source

Thrown at eng/devices/ios.cake:276

	Information("Run UITests project {0}", project);
	RunTestWithLocalDotNet(project, config, pathDotnet: toolPath, noBuild: true, resultsFileNameWithoutExtension: resultsFileName);
	Information("UI Tests completed.");
}

void ExecuteBuildUITestApp(string appProject, string device, string binDir, string config, string tfm, string rid, string toolPath)
{
	Information($"Building UI Test app: {appProject}");
	Information($"USE_NATIVE_AOT: {USE_NATIVE_AOT}");

	var projectName = System.IO.Path.GetFileNameWithoutExtension(appProject);
	var binlog = $"{binDir}/{projectName}-{config}-ios.binlog";

	if (USE_NATIVE_AOT && config.Equals("Debug", StringComparison.OrdinalIgnoreCase))
	{
		var errMsg = $"Error: Running UI tests with NativeAOT is only supported in Release configuration";
		Error(errMsg);
		throw new Exception(errMsg);
	}


	DotNetBuild(appProject, new DotNetBuildSettings
	{
		Configuration = config,
		Framework = tfm,
		ToolPath = toolPath,
		ArgumentCustomization = args =>
		{
			args
			.Append("/p:BuildIpa=true")
			.Append($"/p:_UseNativeAot={USE_NATIVE_AOT}")
			.Append($"/p:RuntimeIdentifier={rid}")
			.Append("/bl:" + binlog)
			.Append("/tl");

			return args;

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Set --configuration=Release (or -c Release) when running with USE_NATIVE_AOT enabled.
  2. If you need a debuggable build, disable USE_NATIVE_AOT rather than forcing Debug.
  3. In CI, derive configuration from the runtime variant so NativeAOT legs always use Release.

Example fix

// before
if (USE_NATIVE_AOT && config.Equals("Debug", StringComparison.OrdinalIgnoreCase))
{
    var errMsg = $"Error: Running UI tests with NativeAOT is only supported in Release configuration";
    Error(errMsg); throw new Exception(errMsg);
}

// after — normalize the config and warn instead of throwing when the intent is clear
if (USE_NATIVE_AOT && config.Equals("Debug", StringComparison.OrdinalIgnoreCase))
{
    config = "Release";
    Warning($"USE_NATIVE_AOT forces Release configuration; continuing with -c {config}.");
}
Defensive patterns

Strategy: validation

Validate before calling

// Reject NativeAOT+Debug before invoking the build
if (USE_NATIVE_AOT && config.Equals("Debug", StringComparison.OrdinalIgnoreCase))
    throw new Exception("NativeAOT requires Release configuration; pass -c Release or disable USE_NATIVE_AOT.");

Prevention

When it happens

Trigger: Passing --configuration=Debug (or leaving the default Debug) while USE_NATIVE_AOT=true; a CI matrix leg that sets RUNTIME_VARIANT=nativeaot but forgets to flip configuration to Release; combining a Debug device-test config with the NativeAOT runtime variant.

Common situations: Copy-pasting a Debug test invocation and adding a NativeAOT flag; CI template that defaults CONFIGURATION to Debug; local developer testing NativeAOT behavior without changing config.

Related errors


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