microsoft/aspire · error · ArgumentException

Endpoint must be a string, endpoint reference, or reference…

Error message

Endpoint must be a string, endpoint reference, or reference expression.

What it means

Thrown by WithMcpToolForPolyglot when the endpoint argument is not one of the three supported shapes: string, EndpointReference, or ReferenceExpression. This polyglot-facing overload does a runtime type switch because non-.NET languages cannot express the overloads, and any other object type falls into the discard arm.

Solutions

  1. Pass the endpoint as a plain string (absolute https URL).
  2. Pass an EndpointReference from a project/container resource endpoint.
  3. Compose dynamic URLs as a ReferenceExpression (e.g. ReferenceExpression.Create($"{endpoint}/mcp")).
  4. Convert unsupported types to string before calling (e.g. uri.ToString()).

Example fix

// before
builder.WithMcpToolForPolyglot("search", new Uri("https://host/mcp"));
// after
builder.WithMcpToolForPolyglot("search", "https://host/mcp");
Defensive patterns

Strategy: type-guard

Validate before calling

if (endpoint is not (string or EndpointReference or ReferenceExpression))
{
    throw new ArgumentException($"Unsupported endpoint type {endpoint.GetType().Name}; use string, EndpointReference, or ReferenceExpression.", nameof(endpoint));
}

Type guard

static bool IsValidEndpointShape(object? e) => e is string or EndpointReference or ReferenceExpression;

Try / catch

try
{
    builder.WithMcpToolForPolyglot(name, endpoint, options);
}
catch (ArgumentException ex) when (ex.Message.Contains("must be a string, endpoint reference"))
{
    logger.LogError(ex, "Unsupported endpoint type {Type}.", endpoint?.GetType().Name);
    throw;
}

Prevention

When it happens

Trigger: Calling WithMcpToolForPolyglot with a Uri instance, a custom endpoint wrapper type, null boxed object, or any type other than string/EndpointReference/ReferenceExpression.

Common situations: Polyglot (Python/TypeScript) callers passing their language's native URL object which marshals to Uri or another unmapped type; refactoring code that previously used a different endpoint type; passing an endpoint built by an incompatible library version.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxBuilderExtensions.cs:292

    /// <ats-returns>The resource builder.</ats-returns>
    [AspireExport("withMcpTool")]
    internal static IResourceBuilder<FoundryToolboxResource> WithMcpToolForPolyglot(
        this IResourceBuilder<FoundryToolboxResource> builder,
        string name,
        [AspireUnion(typeof(string), typeof(EndpointReference), typeof(ReferenceExpression))] object endpoint,
        FoundryToolboxMcpToolOptions? options = null)
    {
        ArgumentNullException.ThrowIfNull(endpoint);

        return endpoint switch
        {
            string endpointString => builder.WithMcpTool(name, endpointString, options),
            EndpointReference endpointReference => builder.WithMcpTool(name, endpointReference, options),
            // ReferenceExpression lets polyglot callers compose URLs (e.g. `refExpr\`${endpoint}/mcp\``)
            // because the polyglot type system can't express a templated string built from a typed
            // endpoint reference any other way.
            ReferenceExpression endpointExpression => builder.WithMcpTool(name, endpointExpression, options),
            _ => throw new ArgumentException("Endpoint must be a string, endpoint reference, or reference expression.", nameof(endpoint))
        };
    }

    /// <summary>
    /// Adds an Azure AI Search tool definition to the Toolbox.
    /// </summary>
    /// <param name="builder">The resource builder for the Toolbox.</param>
    /// <param name="name">The tool name.</param>
    /// <param name="search">The Azure AI Search resource backing the tool.</param>
    /// <param name="indexName">The search index name.</param>
    /// <param name="description">An optional description of the Azure AI Search tool.</param>
    /// <returns>A reference to the <see cref="IResourceBuilder{T}"/> for chaining.</returns>
    /// <ats-returns>The resource builder.</ats-returns>
    [AspireExport]
    public static IResourceBuilder<FoundryToolboxResource> WithAISearchTool(
        this IResourceBuilder<FoundryToolboxResource> builder,
        string name,
        IResourceBuilder<AzureSearchResource> search,

View on GitHub (pinned to 25830f84bd)