microsoft/aspire · critical · InvalidOperationException

External service must have either a URI or a URL parameter…

Error message

External service must have either a URI or a URL parameter defined.

What it means

Thrown by YarpCluster.GetAddressFromExternalService when an ExternalServiceResource has neither a resolved URI nor a URL parameter. The library requires external services used as YARP cluster destinations to resolve to an absolute address so the reverse proxy knows where to forward requests. The comment notes the ExternalServiceResource should normally guarantee a valid absolute URI, so this usually indicates the resource was configured without any URL information.

Solutions

  1. Set the external service URI explicitly, e.g. builder.AddExternalService("api", "https://api.example.com").
  2. If the URL is dynamic, pass a parameter via the URL-parameter overload so externalService.UrlParameter is populated.
  3. Verify the resource producing the URL parameter resolves at runtime (check the parameter's value/env var is not null).

Example fix

// before
var api = builder.AddExternalService("api");
// after
var api = builder.AddExternalService("api", "https://api.example.com");
Defensive patterns

Strategy: validation

Validate before calling

if (externalService.UrlParameter is null && externalService.Uri is null)
{
    throw new InvalidOperationException($"External service '{externalService.Name}' has no URI or URL parameter configured.");
}

Prevention

When it happens

Trigger: Calling ResolveTargets against an ExternalServiceResource whose Uri is null and whose UrlParameter is null, so GetAddressFromExternalService falls past both lookups and throws InvalidOperationException.

Common situations: Declaring builder.AddExternalService(name) without a URI; removing or renaming the environment variable / parameter that supplies the URL at runtime; constructing an external service resource manually in code without calling the URL-providing overloads.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at src/Aspire.Hosting.Yarp/ConfigurationBuilder/YarpCluster.cs:170

            (false, true) => "http",
            _ => throw new ArgumentException("Cannot find a http or https endpoint for this resource.", nameof(resource))
        };

        return [$"{scheme}://{resourceName}"];
    }

    private static object GetAddressFromExternalService(ExternalServiceResource externalService)
    {
        if (externalService.Uri is not null)
        {
            return externalService.Uri.ToString();
        }
        if (externalService.UrlParameter is not null)
        {
            return externalService.UrlParameter;
        }
        // This shouldn't get to here as the ExternalServiceResource should ensure the URL is a valid absolute URI.
        throw new InvalidOperationException("External service must have either a URI or a URL parameter defined.");
    }
}

/// <summary>
/// Provides extension methods for configuring a YARP cluster.
/// </summary>
public static class YarpClusterExtensions
{
    /// <summary>
    /// Set the ForwarderRequestConfig for the cluster.
    /// </summary>
    /// <remarks>This overload is not available in polyglot app hosts. Use the DTO-based overload instead.</remarks>
    [AspireExportIgnore(Reason = "ForwarderRequestConfig is not ATS-compatible. Use the DTO-based overload instead.")]
    public static YarpCluster WithForwarderRequestConfig(this YarpCluster cluster, ForwarderRequestConfig config)
    {
        cluster.Configure(c => c with { HttpRequest = config });
        return cluster;
    }

View on GitHub (pinned to 25830f84bd)