{"record":{"id":"8e97085bc024e219","repo":"microsoft/aspire","slug":"knownconfignames-resourceserviceendpointurl-must-contain-a","errorCode":null,"errorMessage":"{KnownConfigNames.ResourceServiceEndpointUrl} must contain a local loopback address.","messagePattern":"(.+?) must contain a local loopback address\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"critical","filePath":"src/Aspire.Hosting/Dashboard/DashboardServiceHost.cs","lineNumber":208,"sourceCode":"            return new ResourceServiceEndpointInfo(ip, effectivePort, UseListenLocalhost: false, scheme);\n        }\n        else if (configuredUri.IsLoopback || IsLocalhostOrLocalhostTld(configuredUri))\n        {\n            // For \"localhost\" or *.localhost hosts, bind to both IPv4 and IPv6 loopback.\n            // Kestrel does not support ListenLocalhost with port 0, so fall back to\n            // binding on IPv4 loopback when a dynamic port is needed.\n            if (effectivePort == 0)\n            {\n                return new ResourceServiceEndpointInfo(IPAddress.Loopback, Port: 0, UseListenLocalhost: false, scheme);\n            }\n            else\n            {\n                return new ResourceServiceEndpointInfo(IPAddress.Loopback, effectivePort, UseListenLocalhost: true, scheme);\n            }\n        }\n        else\n        {\n            throw new ArgumentException($\"{KnownConfigNames.ResourceServiceEndpointUrl} must contain a local loopback address.\");\n        }\n    }\n\n    /// <summary>\n    /// Determines the scheme for the resource service endpoint. When a URI is explicitly\n    /// configured, its scheme is used. When no URI is provided, defaults to HTTPS unless\n    /// unsecured transport is explicitly allowed.\n    /// </summary>\n    internal static string ResolveScheme(Uri? configuredUri, bool allowUnsecuredTransport)\n    {\n        if (configuredUri is not null)\n        {\n            return configuredUri.Scheme;\n        }\n\n        return allowUnsecuredTransport ? \"http\" : \"https\";\n    }\n","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/Dashboard/DashboardServiceHost.cs#L190-L226","documentation":"DashboardServiceHost resolves the resource service endpoint from KnownConfigNames.ResourceServiceEndpointUrl and requires it to be a local loopback address, since the dashboard connects to the AppHost's resource service locally. An ArgumentException is thrown when the configured URL host is not loopback (e.g. a public hostname or LAN IP).","triggerScenarios":"Setting ResourceServiceEndpointUrl (environment/config) to a non-loopback host such as https://myhost.example.com or a LAN IP, then starting the dashboard service host.","commonSituations":"Container/remote-dev setups where developers point the dashboard at a remote AppHost; misconfigured port-forward URLs; copying config from a machine with a different hostname.","solutions":["Change ResourceServiceEndpointUrl to a loopback address (127.0.0.1, ::1, or localhost) with the correct port.","If the AppHost truly runs remotely, tunnel the resource service to localhost (e.g. SSH/VS Code port forwarding) and use the local endpoint.","Remove the ResourceServiceEndpointUrl override to let the host auto-discover the endpoint from the AppHost.","Check for typos or stale hostnames in launchSettings/environment configuration."],"exampleFix":"// before\n// ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL=https://devbox.contoso.com:18975\n// after\n// ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL=http://127.0.0.1:18975  (or tunnel the remote port to localhost)","handlingStrategy":"validation","validationCode":"var url = new Uri(Environment.GetEnvironmentVariable(\"ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL\")!);\nvar loopback = new[] { IPAddress.Loopback, IPAddress.IPv6Loopback };\nvar isLoopback = url.Host is \"localhost\" || (IPAddress.TryParse(url.Host, out var ip) && loopback.Contains(ip));\nif (!isLoopback) throw new ArgumentException($\"{url} must be a loopback address.\");","typeGuard":"bool IsLoopback(Uri u) => u.Host == \"localhost\" || (IPAddress.TryParse(u.Host, out var ip) && (IPAddress.Loopback.Equals(ip) || IPAddress.IPv6Loopback.Equals(ip)));","tryCatchPattern":"try { startDashboardHost(); } catch (ArgumentException ex) when (ex.Message.Contains(\"loopback\")) { logger.LogError(ex, \"Fix ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL to point at 127.0.0.1/localhost.\"); }","preventionTips":["Never point the dashboard's resource service URL at remote hosts","Use port forwarding/tunnels to expose remote AppHosts on localhost","Validate configured URLs in launchSettings before starting"],"tags":["configuration","url","loopback","startup"],"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-21T04:17:39.646Z"}