{"record":{"id":"31bf799ac3037f91","repo":"microsoft/aspire","slug":"resource-resource-name-is-missing-mauibuildinfoannotation","errorCode":null,"errorMessage":"Resource '{resource.Name}' is missing MauiBuildInfoAnnotation. Cannot proceed with build — the semaphore would be held indefinitely.","messagePattern":"Resource '(.+?)' is missing MauiBuildInfoAnnotation\\. Cannot proceed with build — the semaphore would be held indefinitely\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"critical","filePath":"src/Aspire.Hosting.Maui/Lifecycle/MauiBuildQueueEventSubscriber.cs","lineNumber":175,"sourceCode":"            if (semaphoreAcquired && releaseInFinally)\n            {\n                ReleaseSemaphoreSafely(semaphore);\n                logger.LogDebug(\"Released build lock (resource '{ResourceName}').\", resource.Name);\n            }\n\n            queueAnnotation.ResourceCancellations.TryRemove(resource.Name, out _);\n        }\n    }\n\n    /// <summary>\n    /// Runs <c>dotnet build</c> as a subprocess and pipes its output to the resource logger.\n    /// </summary>\n    internal virtual async Task RunBuildAsync(IResource resource, ILogger logger, CancellationToken cancellationToken)\n    {\n        if (!resource.TryGetLastAnnotation<MauiBuildInfoAnnotation>(out var buildInfo))\n        {\n            logger.LogWarning(\"No build info annotation found for resource '{ResourceName}'. Startup cannot proceed.\", resource.Name);\n            throw new InvalidOperationException(\n                $\"Resource '{resource.Name}' is missing MauiBuildInfoAnnotation. \" +\n                \"Cannot proceed with build — the semaphore would be held indefinitely.\");\n        }\n\n        // Match DCP's launch configuration so the Run target starts the exact outputs produced\n        // by this serialized build.\n        var args = new List<string> { \"build\", buildInfo.ProjectPath };\n\n        if (!string.IsNullOrEmpty(buildInfo.TargetFramework))\n        {\n            args.Add(\"-f\");\n            args.Add(buildInfo.TargetFramework);\n        }\n\n        if (!string.IsNullOrEmpty(buildInfo.Configuration))\n        {\n            args.Add(\"--configuration\");\n            args.Add(buildInfo.Configuration);","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Maui/Lifecycle/MauiBuildQueueEventSubscriber.cs#L157-L193","documentation":"Before a MAUI resource is started, MauiBuildQueueEventSubscriber serializes builds by acquiring a semaphore. The release of that semaphore depends on build-info data, so if the resource lacks a MauiBuildInfoAnnotation the subscriber throws InvalidOperationException rather than deadlocking on the semaphore. Startup of that resource cannot proceed.","triggerScenarios":"A resource passed through OnBeforeResourceStartedEvent into RunBuildAsync that was not created/configured via the MAUI hosting APIs that add MauiBuildInfoAnnotation (src/Aspire.Hosting.Maui/Lifecycle/MauiBuildQueueEventSubscriber.cs:175).","commonSituations":"Adding a plain ProjectResource or custom resource and expecting MAUI build queue behavior; calling a MAUI extension on the wrong resource type; a custom pipeline stripping annotations; version drift where the annotation is added by a newer extension method.","solutions":["Create the MAUI platform/project resource through the intended AddMaui*/With* APIs so MauiBuildInfoAnnotation is attached.","Manually add the annotation before start: resource.Annotations.Add(new MauiBuildInfoAnnotation(...)) if constructing resources by hand.","Confirm the resource reaching the event is a MAUI resource — filter in your subscriber with TryGetLastAnnotation<MauiBuildInfoAnnotation> before invoking build logic."],"exampleFix":"// before\nbuilder.AddResource(myMauiApp); // no MAUI annotations\n// after\nbuilder.AddMauiProject(\"my-maui-app\", \"MyMauiApp.csproj\"); // adds MauiBuildInfoAnnotation","handlingStrategy":"validation","validationCode":"if (!resource.TryGetLastAnnotation<MauiBuildInfoAnnotation>(out _)) throw new InvalidOperationException($\"{resource.Name} is not a MAUI resource; use AddMauiProject/AddMaui* APIs.\");","typeGuard":"static bool IsMauiBuildable(IResource r) => r.TryGetLastAnnotation<MauiBuildInfoAnnotation>(out _);","tryCatchPattern":"try { await subscriber.OnBeforeResourceStartedAsync(evt, ct); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"MauiBuildInfoAnnotation\")) { /* resource was not built via MAUI APIs */ }","preventionTips":["Create MAUI resources only via AddMauiProject/AddMaui* extension APIs","Filter MAUI lifecycle subscribers on TryGetLastAnnotation<MauiBuildInfoAnnotation>","Don't strip annotations in custom model transformations"],"tags":["maui","lifecycle","annotations","apphost"],"backgroundTag":"missing-dependency","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}