microsoft/aspire · error · DistributedApplicationException

The configured OTLP endpoint URL

Error message

The configured OTLP endpoint URL '{url}' from '{configKey}' must be an absolute locally reachable HTTP or HTTPS URL with a port between 1 and 65535.

What it means

ResolveConfiguredOtlpEndpoint reads a user-configured OTLP endpoint URL from configuration (configKey) and validates it in CreateConfiguredOtlpEndpointTarget. The URL must be absolute, HTTP or HTTPS, point at a locally reachable dashboard binding, and have a valid port (1-65535). Any violation throws DistributedApplicationException naming the offending URL and config key.

Solutions

  1. Set the config key to an absolute URL like http://localhost:PORT or https://localhost:PORT matching the dashboard's actual OTLP endpoint binding.
  2. Check the config key name in the message is the one you intend; fix typos and ensure only one value is set.
  3. Verify IsLocalDashboardBinding expectations: use localhost/127.0.0.1 (the locally bound dashboard address), not a remote host.
  4. Ensure the port is explicit and within 1-65535 — append :PORT if the URL omits it.

Example fix

// before
env["DOTNET_DASHBOARD_OTLP_ENDPOINT_URL"] = "tcp://0.0.0.0";
// after
env["DOTNET_DASHBOARD_OTLP_ENDPOINT_URL"] = "http://localhost:18889";
Defensive patterns

Strategy: validation

Validate before calling

bool IsValidOtlpUrl(string? url) =>
    Uri.TryCreate(url, UriKind.Absolute, out var u) &&
    u.Scheme is "http" or "https" &&
    (u.Host is "localhost" or "127.0.0.1") &&
    u.Port is >= 1 and <= 65535;

Type guard

static bool IsAbsoluteLocalHttpUrl(string? s) => Uri.TryCreate(s, UriKind.Absolute, out var u) && u.Scheme is "http" or "https" && u.Port is >= 1 and <= 65535;

Try / catch

try { await startAsync(); } catch (DistributedApplicationException ex) when (ex.Message.Contains("OTLP endpoint URL")) { // fix the config value named in the message }

Prevention

When it happens

Trigger: Setting the OTLP endpoint configuration key (e.g. an env var like DOTNET_DASHBOARD_OTLP_ENDPOINT_URL or the MAUI-specific config key) to a relative URL, a non-http scheme (tcp), a remote host that fails IsLocalDashboardBinding, or a port of 0/out of range (src/Aspire.Hosting.Maui/MauiOtlpExtensions.cs:252).

Common situations: Typo'd or truncated env values; copying an https URL with a wrong/remote host into a local-run scenario; using the gRPC 'tcp' scheme out of habit; port 0 or empty port in the configured URL; CI containers where the dashboard binds to an unexpected host.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/f8da49e3903fe905. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Maui/MauiOtlpExtensions.cs:252

        if (string.IsNullOrWhiteSpace(configuredGrpcUrl) && string.IsNullOrWhiteSpace(configuredHttpUrl))
        {
            return null;
        }

        return !string.IsNullOrWhiteSpace(configuredHttpUrl)
            ? CreateConfiguredOtlpEndpointTarget(configuredHttpUrl, KnownConfigNames.DashboardOtlpHttpEndpointUrl, OtlpHttpProtobufProtocol)
            : CreateConfiguredOtlpEndpointTarget(configuredGrpcUrl!, KnownConfigNames.DashboardOtlpGrpcEndpointUrl, OtlpGrpcProtocol);
    }

    private static OtlpEndpointTarget CreateConfiguredOtlpEndpointTarget(string url, string configKey, string protocol)
    {
        if (!Uri.TryCreate(url, UriKind.Absolute, out var uri) ||
            uri.Scheme is not ("http" or "https") ||
            !IsLocalDashboardBinding(uri) ||
            uri.Port is < 1 or > 65535)
        {
            throw new DistributedApplicationException($"The configured OTLP endpoint URL '{url}' from '{configKey}' must be an absolute locally reachable HTTP or HTTPS URL with a port between 1 and 65535.");
        }

        return new OtlpEndpointTarget(uri.Scheme, uri.Port, protocol);
    }

    private static string ResolveDynamicDashboardOtlpScheme(IConfiguration configuration)
        => configuration.GetBool(KnownConfigNames.AllowUnsecuredTransport) is true ? "http" : "https";

    private static async ValueTask<OtlpEndpointTarget?> TryResolveDashboardOtlpEndpointAsync(
        IResource resource,
        IServiceProvider services,
        bool waitForRuntimeSnapshot,
        TimeSpan runtimeSnapshotResolutionTimeout,
        CancellationToken cancellationToken)
    {
        if (!string.Equals(resource.Name, KnownResourceNames.AspireDashboard, StringComparisons.ResourceName) || resource is not IResourceWithEndpoints dashboardResource)
        {
            return null;

View on GitHub (pinned to 25830f84bd)