microsoft/aspire · error · InvalidOperationException
GatewayAppsAnnotation not found on resource.
Error message
GatewayAppsAnnotation not found on resource.
What it means
GetRegisteredApps reads the GatewayAppsAnnotation from the gateway resource to enumerate the registered Blazor apps. If the annotation is absent — meaning WithBlazorApp (or equivalent registration) was never applied to this resource — the helper throws an InvalidOperationException.
Solutions
- Call gateway.WithBlazorApp(...) (which adds GatewayAppsAnnotation) before code that reads registered apps.
- Register at least one Blazor app with the gateway via the documented extension APIs.
- Guard with resource.TryGetLastAnnotation<GatewayAppsAnnotation> before consuming apps.
- Ensure you're inspecting the gateway resource itself, not the client app resource.
Example fix
// before
var apps = GetRegisteredApps(gateway.Resource);
// after
if (!gateway.Resource.TryGetLastAnnotation<GatewayAppsAnnotation>(out var appsAnn))
{
throw new InvalidOperationException("Call WithBlazorApp on the gateway before starting it.");
}
var apps = appsAnn.Apps; Defensive patterns
Strategy: type-guard
Validate before calling
if (!gateway.Resource.TryGetLastAnnotation<GatewayAppsAnnotation>(out var apps))
{
throw new InvalidOperationException("No Blazor apps registered; call WithBlazorApp first.");
} Type guard
bool TryGetGatewayApps(IResource r, out IReadOnlyList<BlazorApp> apps)
{
if (r.TryGetLastAnnotation<GatewayAppsAnnotation>(out var a)) { apps = a.Apps; return true; }
apps = default; return false;
} Try / catch
try { var apps = GetRegisteredApps(gateway.Resource); } catch (InvalidOperationException ex) when (ex.Message.Contains("GatewayAppsAnnotation")) { logger.LogError(ex, "Call WithBlazorApp before consuming gateway apps"); throw; } Prevention
- Always register apps via WithBlazorApp before gateway-dependent wiring.
- Never hand-build gateway resources without the annotation.
- Use TryGetLastAnnotation defensively in custom extension code.
When it happens
Trigger: Environment-callback or endpoint wiring code calls GetRegisteredApps on a gateway resource that never received GatewayAppsAnnotation, e.g. invoking WithBlazorApp-dependent configuration on a gateway built without registering any Blazor app.
Common situations: Calling low-level extension methods out of order; applying WithEnvironment-based wiring manually before any WithBlazorApp call; a refactor renamed/removed the registration call.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Publishing a DotnetProjectResource-backed Blazor gateway is…
- The gateway ' ' must define an HTTP or HTTPS endpoint.
- At least one gateway endpoint (HTTP or HTTPS) must be…
- Failed to discover the Blazor WebAssembly client project for
- not found at ' '. Ensure the Aspire.Hosting.Blazor package…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/a774148ba505737d.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Blazor/BlazorGatewayExtensions.cs:706
{
if (resource.TryGetLastAnnotation<GatewayAppsAnnotation>(out var existing))
{
return existing;
}
var newAnnotation = new GatewayAppsAnnotation();
resource.Annotations.Add(newAnnotation);
return newAnnotation;
}
private static List<GatewayAppRegistration> GetRegisteredApps(IResource resource)
{
if (resource.TryGetLastAnnotation<GatewayAppsAnnotation>(out var apps))
{
return apps.Apps;
}
throw new InvalidOperationException("GatewayAppsAnnotation not found on resource.");
}
private static List<EndpointAnnotation> GetAllocatedEndpoints(IResource resource)
{
var endpoints = new List<EndpointAnnotation>();
foreach (var annotation in resource.Annotations)
{
if (annotation is EndpointAnnotation ep && ep.AllocatedEndpoint is not null)
{
endpoints.Add(ep);
}
}
return endpoints;
}
private static ImmutableArray<UrlSnapshot> BuildClientUrls(
List<EndpointAnnotation> endpoints, string pathPrefix)
{View on GitHub (pinned to 25830f84bd)