{"record":{"id":"0ec05011b7673798","repo":"microsoft/aspire","slug":"build-for-resource-resource-name-timed-out-after","errorCode":null,"errorMessage":"Build for resource '{resource.Name}' timed out after {BuildTimeout:c}.","messagePattern":"Build for resource '(.+?)' timed out after (.+?)\\.","errorType":"exception","errorClass":"TimeoutException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Maui/Lifecycle/MauiBuildQueueEventSubscriber.cs","lineNumber":235,"sourceCode":"        var token = timeoutCts.Token;\n\n        using var process = new Process { StartInfo = psi };\n\n        process.Start();\n\n        // Pipe stdout/stderr to the resource logger so output is visible in the dashboard.\n        var stdoutTask = PipeOutputAsync(process.StandardOutput, logger, LogLevel.Information, token);\n        var stderrTask = PipeOutputAsync(process.StandardError, logger, LogLevel.Warning, token);\n\n        try\n        {\n            await process.WaitForExitAsync(token).ConfigureAwait(false);\n        }\n        catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested)\n        {\n            // The timeout CTS fired, not the caller's token — this is a build timeout.\n            TryKillProcess(process, logger);\n            throw new TimeoutException(\n                $\"Build for resource '{resource.Name}' timed out after {BuildTimeout:c}.\");\n        }\n        catch (OperationCanceledException)\n        {\n            TryKillProcess(process, logger);\n            throw;\n        }\n        finally\n        {\n            // Always drain remaining output — even on cancellation the process was killed\n            // and the streams will reach EOF, so the tasks will complete promptly.\n            await Task.WhenAll(stdoutTask, stderrTask).ConfigureAwait(false);\n        }\n\n        if (process.ExitCode != 0)\n        {\n            throw new InvalidOperationException(\n                $\"Build failed for resource '{resource.Name}' with exit code {process.ExitCode}.\");","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Maui/Lifecycle/MauiBuildQueueEventSubscriber.cs#L217-L253","documentation":"RunBuildAsync runs the MAUI build (dotnet build/run pipeline) with a per-resource build timeout (BuildTimeout). When the build process is killed because that timeout elapsed — not because the caller cancelled — the method kills the process and throws TimeoutException so the resource fails to start with a clear cause.","triggerScenarios":"The MAUI build (e.g. targeting iOS/Android/MacCatalyst workloads) takes longer than BuildTimeout; the timeout CancellationTokenSource fires during process.WaitForExitAsync while the caller token is still live (src/Aspire.Hosting.Maui/Lifecycle/MauiBuildQueueEventSubscriber.cs:235).","commonSituations":"First builds that restore workloads and NuGet packages (cold caches, slow networks); large MAUI solutions; slow CI machines or emulator-heavy targets; setting an aggressive custom BuildTimeout.","solutions":["Increase the build timeout configuration (BuildTimeout) to accommodate cold restore/workload installs.","Warm up the build by running dotnet build for the MAUI project once outside Aspire so subsequent queued builds are fast.","Re-run after transient network/NuGet slowness; pre-restore packages (dotnet restore) to reduce build time.","If cancellation is seen instead, check whether the caller token fired rather than the timeout CTS."],"exampleFix":"// before\n.WithBuildTimeout(TimeSpan.FromMinutes(5));\n// after\n.WithBuildTimeout(TimeSpan.FromMinutes(20)); // allow first-run workload restore","handlingStrategy":"retry","validationCode":"// estimate: measure a cold build once\nvar sw = Stopwatch.StartNew(); RunDotnetBuild(); sw.Stop(); if (sw.Elapsed > configuredTimeout) raiseTimeout();","typeGuard":null,"tryCatchPattern":"try { await startMauiResourceAsync(); } catch (TimeoutException ex) when (ex.Message.Contains(\"timed out after\")) { /* raise BuildTimeout and retry the build once */ }","preventionTips":["Set a generous BuildTimeout that covers cold restore and workload installs","Warm the build cache (dotnet build) before running the AppHost","Pre-restore NuGet packages and workloads on CI images","Watch for slow networks during first-run package restore"],"tags":["maui","timeout","build","lifecycle"],"backgroundTag":"request-timeout","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}