{"record":{"id":"f8da49e3903fe905","repo":"microsoft/aspire","slug":"the-configured-otlp-endpoint-url-url-from-configkey-must-be","errorCode":null,"errorMessage":"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.","messagePattern":"The configured OTLP endpoint URL '(.+?)' from '(.+?)' must be an absolute locally reachable HTTP or HTTPS URL with a port between 1 and 65535\\.","errorType":"exception","errorClass":"DistributedApplicationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Maui/MauiOtlpExtensions.cs","lineNumber":252,"sourceCode":"\n        if (string.IsNullOrWhiteSpace(configuredGrpcUrl) && string.IsNullOrWhiteSpace(configuredHttpUrl))\n        {\n            return null;\n        }\n\n        return !string.IsNullOrWhiteSpace(configuredHttpUrl)\n            ? CreateConfiguredOtlpEndpointTarget(configuredHttpUrl, KnownConfigNames.DashboardOtlpHttpEndpointUrl, OtlpHttpProtobufProtocol)\n            : CreateConfiguredOtlpEndpointTarget(configuredGrpcUrl!, KnownConfigNames.DashboardOtlpGrpcEndpointUrl, OtlpGrpcProtocol);\n    }\n\n    private static OtlpEndpointTarget CreateConfiguredOtlpEndpointTarget(string url, string configKey, string protocol)\n    {\n        if (!Uri.TryCreate(url, UriKind.Absolute, out var uri) ||\n            uri.Scheme is not (\"http\" or \"https\") ||\n            !IsLocalDashboardBinding(uri) ||\n            uri.Port is < 1 or > 65535)\n        {\n            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.\");\n        }\n\n        return new OtlpEndpointTarget(uri.Scheme, uri.Port, protocol);\n    }\n\n    private static string ResolveDynamicDashboardOtlpScheme(IConfiguration configuration)\n        => configuration.GetBool(KnownConfigNames.AllowUnsecuredTransport) is true ? \"http\" : \"https\";\n\n    private static async ValueTask<OtlpEndpointTarget?> TryResolveDashboardOtlpEndpointAsync(\n        IResource resource,\n        IServiceProvider services,\n        bool waitForRuntimeSnapshot,\n        TimeSpan runtimeSnapshotResolutionTimeout,\n        CancellationToken cancellationToken)\n    {\n        if (!string.Equals(resource.Name, KnownResourceNames.AspireDashboard, StringComparisons.ResourceName) || resource is not IResourceWithEndpoints dashboardResource)\n        {\n            return null;","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Maui/MauiOtlpExtensions.cs#L234-L270","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Set the config key to an absolute URL like http://localhost:PORT or https://localhost:PORT matching the dashboard's actual OTLP endpoint binding.","Check the config key name in the message is the one you intend; fix typos and ensure only one value is set.","Verify IsLocalDashboardBinding expectations: use localhost/127.0.0.1 (the locally bound dashboard address), not a remote host.","Ensure the port is explicit and within 1-65535 — append :PORT if the URL omits it."],"exampleFix":"// before\nenv[\"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL\"] = \"tcp://0.0.0.0\";\n// after\nenv[\"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL\"] = \"http://localhost:18889\";","handlingStrategy":"validation","validationCode":"bool IsValidOtlpUrl(string? url) =>\n    Uri.TryCreate(url, UriKind.Absolute, out var u) &&\n    u.Scheme is \"http\" or \"https\" &&\n    (u.Host is \"localhost\" or \"127.0.0.1\") &&\n    u.Port is >= 1 and <= 65535;","typeGuard":"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;","tryCatchPattern":"try { await startAsync(); } catch (DistributedApplicationException ex) when (ex.Message.Contains(\"OTLP endpoint URL\")) { // fix the config value named in the message }","preventionTips":["Use absolute http(s)://localhost:PORT URLs for OTLP endpoint config","Never use 'tcp' scheme or port 0 in OTLP URL config","Point the URL at the local dashboard binding, not a remote host","Validate configured env vars in launchSettings/CI before running the AppHost"],"tags":["maui","otlp","configuration","url-validation"],"backgroundTag":"invalid-config-value","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"}