microsoft/aspire · error · InvalidOperationException
The MAUI OTLP dev tunnel configuration was not initialized…
Error message
The MAUI OTLP dev tunnel configuration was not initialized before tunnel startup.
What it means
WithOtlpDevTunnel defers tunnel setup via closures that capture a tunnelConfig reference initialized later. If the BeforeResourceStartedEvent handler for the dev tunnel fires while tunnelConfig is still null, the captured state was never initialized, so the subscriber throws InvalidOperationException rather than configuring a tunnel blindly.
Solutions
- Ensure WithOtlpDevTunnel is applied to the MAUI resource before the AppHost starts, so initialization runs before the tunnel's BeforeResourceStartedEvent.
- Verify the tunnel resource name matches the one created by WithOtlpDevTunnel (tunnelName) — starting a foreign tunnel resource triggers the guard.
- Don't manually start or reorder the DevTunnelResource; let the MAUI extension manage its lifecycle.
- If reproducing in tests, wait for model construction to finish before triggering resource-start events.
Example fix
// before
var maui = builder.AddMauiProject(...);
builder.AddDevTunnel("otlp-tunnel").WithOtlpDevTunnel(maui); // tunnel created separately, wrong order
// after
maui.WithOtlpDevTunnel(); // extension creates and wires the tunnel itself Defensive patterns
Strategy: validation
Validate before calling
// assert wiring happens before start
if (appModelBuilt) throw new InvalidOperationException("WithOtlpDevTunnel must be applied before builder.Build()/Run()."); Try / catch
try { await startAsync(); } catch (InvalidOperationException ex) when (ex.Message.Contains("tunnel configuration was not initialized")) { /* move WithOtlpDevTunnel earlier in app-model construction */ } Prevention
- Call WithOtlpDevTunnel during model construction, before Build/Run
- Let the extension create and own the DevTunnelResource — don't hand-roll one
- Don't manually start tunnel resources or reorder start events
- Keep MAUI hosting packages at consistent versions
When it happens
Trigger: The BeforeResourceStartedEvent for the DevTunnelResource named tunnelName fires before WithOtlpDevTunnel's initialization path ran (tunnelConfig still null) at src/Aspire.Hosting.Maui/MauiOtlpExtensions.cs:132.
Common situations: Starting the dev tunnel resource before the MAUI OTLP wiring completes; calling WithOtlpDevTunnel on the wrong resource or after the app model started; event ordering changes across Aspire versions; manually starting the tunnel resource in tests.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- The MAUI OTLP dev tunnel configuration was not initialized…
- Build failed for resource
- Build for resource ' ' timed out after .
- Cannot complete task
- Cannot create task for step
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/f15660b3e6a429b6.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Maui/MauiOtlpExtensions.cs:132
var stubBuilder = appBuilder.AddResource(stubResource)
.ExcludeFromManifest();
// Hide the stub from the dashboard UI
stubBuilder.WithHidden().WithInitialState(new CustomResourceSnapshot
{
ResourceType = "OtlpStub",
Properties = []
});
if (configuredOtlpEndpoint is null)
{
appBuilder.Eventing.Subscribe<BeforeResourceStartedEvent>(async (evt, ct) =>
{
if (evt.Resource is DevTunnelResource devTunnelResource &&
string.Equals(devTunnelResource.Name, tunnelName, StringComparisons.ResourceName))
{
var currentTunnelConfig = tunnelConfig ?? throw new InvalidOperationException("The MAUI OTLP dev tunnel configuration was not initialized before tunnel startup.");
if (currentTunnelConfig.IsOtlpEndpointResolved)
{
return;
}
var dashboardResource = appBuilder.Resources.FirstOrDefault(resource =>
string.Equals(resource.Name, KnownResourceNames.AspireDashboard, StringComparisons.ResourceName));
if (dashboardResource is null)
{
var exception = new DistributedApplicationException($"The MAUI OTLP dev tunnel for resource '{parentBuilder.Resource.Name}' requires the Aspire dashboard to be enabled or an explicit OTLP endpoint URL to be configured.");
if (currentTunnelConfig.TryFailOtlpEndpointResolution(exception))
{
throw exception;
}
return;
}
View on GitHub (pinned to 25830f84bd)