microsoft/aspire · error · ArgumentException

MCP tool ' ' cannot both always and never require approval.

Error message

MCP tool '{overlap}' cannot both always and never require approval.

What it means

A single tool name appearing in both the Always and Never approval filters is contradictory — Foundry could not decide whether that tool requires approval. Create detects the first ordinal-intersection name and throws an ArgumentException naming the policy parameter.

Solutions

  1. Remove the conflicting tool name from one of the two lists.
  2. Reclassify the tool into exactly one bucket (always or never).
  3. Compute the lists programmatically so never = allTools - alwaysTools, guaranteeing disjoint sets.
  4. Catch ArgumentException and surface the offending overlap name (it is in the message) to fix config.

Example fix

// before
Always = new() { ToolNames = ["delete", "write"] },
Never  = new() { ToolNames = ["delete"] }
// after
Always = new() { ToolNames = ["delete", "write"] },
Never  = new() { ToolNames = ["read"] }
Defensive patterns

Strategy: validation

Validate before calling

var overlap = always.ToolNames.Intersect(never.ToolNames, StringComparer.Ordinal).FirstOrDefault();
if (overlap is not null) throw new ArgumentException($"'{overlap}' is in both always and never filters.");

Type guard

static bool Disjoint(FoundryToolboxMcpApprovalFilter a, FoundryToolboxMcpApprovalFilter? n) =>
    n is null || !a.ToolNames.Intersect(n.ToolNames ?? [], StringComparer.Ordinal).Any();

Try / catch

try { toolDefinition = CreateMcpTool(...); }
catch (ArgumentException ex) when (ex.Message.Contains("cannot both always and never require approval"))
{ logger.LogError("Remove the conflicting tool from one filter: {Message}", ex.Message); }

Prevention

When it happens

Trigger: Building Always.ToolNames and Never.ToolNames from overlapping sources (e.g. a default list plus an exception list) so a tool like 'delete_item' ends up in both arrays.

Common situations: Merging filter lists from multiple config sources without deduplication by category; a rename causing the same tool to match two different filter rules; templated policy generation producing overlapping sets.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

Thrown at src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxToolDefinition.cs:254

                nameof(policy));
        }

        if (policy.Global is not null &&
            policy.Global is not FoundryToolboxMcpGlobalApprovalMode.Never &&
            policy.Global is not FoundryToolboxMcpGlobalApprovalMode.Always)
        {
            throw new ArgumentOutOfRangeException(
                nameof(policy),
                policy.Global,
                "The global MCP approval mode is not supported.");
        }

        var overlap = always?.ToolNames
            .Intersect(never?.ToolNames ?? [], StringComparer.Ordinal)
            .FirstOrDefault();
        if (overlap is not null)
        {
            throw new ArgumentException(
                $"MCP tool '{overlap}' cannot both always and never require approval.",
                nameof(policy));
        }

        if (always?.ReadOnly is { } alwaysReadOnly && never?.ReadOnly == alwaysReadOnly)
        {
            throw new ArgumentException(
                $"MCP tools with read_only set to '{alwaysReadOnly.ToString().ToLowerInvariant()}' cannot both always and never require approval.",
                nameof(policy));
        }

        return new(policy.Global, always, never);
    }

    public void WriteTo(Utf8JsonWriter writer)
    {
        if (Global is { } global)
        {

View on GitHub (pinned to 25830f84bd)