microsoft/aspire · error · InvalidOperationException
Toolbox ' ' contains duplicate tool names: .
Error message
Toolbox '{name}' contains duplicate tool names: {string.Join(", ", duplicateToolNames)}. What it means
Thrown by FoundryToolboxReconciler.Create when two or more tool definitions in the collection share the same Name (compared with StringComparer.Ordinal). Tool names must be unique within a Toolbox because they become the identifiers the MCP clients invoke; duplicates would be ambiguous. The message lists the offending names.
Solutions
- Rename one of the duplicate tools so every tool name in the Toolbox is unique.
- If tools come from multiple MCP servers with colliding names, prefix names with the server label or scope.
- Deduplicate before calling Create (e.g. DistinctBy(t => t.Name, StringComparer.Ordinal)) and log dropped duplicates.
Example fix
// before
builder.WithMcpTool("search", "https://a.example.com/mcp");
builder.WithMcpTool("search", "https://b.example.com/mcp");
// after
builder.WithMcpTool("a-search", "https://a.example.com/mcp");
builder.WithMcpTool("b-search", "https://b.example.com/mcp"); Defensive patterns
Strategy: validation
Validate before calling
var dupes = tools.GroupBy(t => t.Name, StringComparer.Ordinal).Where(g => g.Count() > 1).Select(g => g.Key).ToArray();
if (dupes.Length > 0)
{
throw new InvalidOperationException($"Duplicate tool names before Toolbox creation: {string.Join(", ", dupes)}");
} Type guard
static bool HasUniqueToolNames(IEnumerable<FoundryToolDefinition> tools) =>
tools.Select(t => t.Name).Distinct(StringComparer.Ordinal).Count() == tools.Count(); Try / catch
try
{
var toolbox = FoundryToolboxReconciler.Create(name, description, tools, metadata);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("duplicate tool names"))
{
logger.LogError(ex, "Toolbox {Name} has duplicate tool names; rename one of the registrations.", name);
throw;
} Prevention
- Prefix tool names with their source MCP server label when aggregating from multiple servers.
- Add a unit test asserting tool-name uniqueness in the app model.
- Deduplicate with DistinctBy(t => t.Name) and log dropped duplicates when merging tool lists.
When it happens
Trigger: Calling Create with a tools collection containing two entries whose Name properties are identical — e.g. the same WithMcpTool name used twice, or tools aggregated from multiple sources that both register a tool named 'search'.
Common situations: Merging tool lists from config plus code where a name collides; loop that adds the same tool per-resource without suffixing names; copy-paste duplication in the app model; two MCP servers both exposing a tool with the same name added under one Toolbox.
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
- Endpoint must be a string, endpoint reference, or reference…
- The MCP endpoint must be a Foundry-reachable absolute HTTPS…
- Toolbox ' ' must contain at least one tool.
- -32602
- A discovered Toolbox tool did not have a name.
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/142619208f18a395.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxReconciler.cs:76
ArgumentException.ThrowIfNullOrWhiteSpace(description);
ArgumentNullException.ThrowIfNull(tools);
ArgumentNullException.ThrowIfNull(metadata);
if (tools.Count == 0)
{
throw new InvalidOperationException($"Toolbox '{name}' must contain at least one tool.");
}
var duplicateToolNames = tools
.GroupBy(tool => tool.Name, StringComparer.Ordinal)
.Where(group => group.Count() > 1)
.Select(group => group.Key)
.Order(StringComparer.Ordinal)
.ToArray();
if (duplicateToolNames.Length > 0)
{
throw new InvalidOperationException(
$"Toolbox '{name}' contains duplicate tool names: {string.Join(", ", duplicateToolNames)}.");
}
var duplicateMcpServerLabels = tools
.Where(tool => tool.McpServerLabel is not null)
.GroupBy(tool => tool.McpServerLabel!, StringComparer.Ordinal)
.Where(group => group.Count() > 1)
.Select(group => group.Key)
.Order(StringComparer.Ordinal)
.ToArray();
if (duplicateMcpServerLabels.Length > 0)
{
throw new InvalidOperationException(
$"Toolbox '{name}' contains duplicate MCP server labels: {string.Join(", ", duplicateMcpServerLabels)}.");
}
var maximumUserMetadataEntries = MaximumMetadataEntries - s_reservedMetadataKeys.Length;
if (metadata.Count > maximumUserMetadataEntries)View on GitHub (pinned to 25830f84bd)