github/copilot-sdk · error · ArgumentException

Invalid tool name: must not be null or empty.

Error message

Invalid {kind} tool name: must not be null or empty.

What it means

ToolSet.ValidateName rejects tool names that are null or the empty string when adding tools of any kind (built-in, custom, MCP). Every tool in the set must have a usable identifier; the wildcard "*" is checked next and allowed, but empty is never valid.

Solutions

  1. Provide a non-empty name string to AddBuiltIn/AddCustom/AddMcp.
  2. Filter or skip tool definitions with null/empty names before adding them.
  3. Guard in your own loading code with string.IsNullOrEmpty and log/skip the offending entry.
  4. Catch ArgumentException (paramName == "name") around batch tool registration to identify the bad entry.

Example fix

// before
toolSet.AddCustom(config.Name); // config.Name == ""

// after
if (!string.IsNullOrEmpty(config.Name)) toolSet.AddCustom(config.Name);
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrEmpty(name))
    throw new ArgumentException("Tool name must not be null or empty", nameof(name));

Type guard

static bool IsValidToolNameBase(string? name) => !string.IsNullOrEmpty(name);

Try / catch

try { toolSet.AddCustom(name); }
catch (ArgumentException ex) when (ex.ParamName == "name" && ex.Message.Contains("must not be null or empty"))
{ logger.LogError("Skipping tool with blank name"); }

Prevention

When it happens

Trigger: Calling ToolSet.AddBuiltIn(null), AddCustom(""), or AddMcp with an empty name — typically when a tool entry was constructed from data where the name field is missing or empty.

Common situations: MCP servers or config files listing tools without a name; deserialized tool metadata with null Name; string.Split/parse producing empty entries passed to Add*.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/c0fc70c8e5b31e84. Report an issue: GitHub.

Appendix: source

Thrown at dotnet/src/ToolSet.cs:104

    /// Adds an MCP tool pattern. Matches tools advertised by any configured
    /// MCP server.
    /// </summary>
    /// <param name="toolName">The runtime's canonical wire name for the MCP
    /// tool (e.g. <c>"github-list_issues"</c>), or <c>"*"</c> to match all
    /// MCP tools from any server.</param>
    /// <returns>This <see cref="ToolSet"/> for chaining.</returns>
    public ToolSet AddMcp(string toolName)
    {
        ValidateName("mcp", toolName);
        Add($"mcp:{toolName}");
        return this;
    }

    private static void ValidateName(string kind, string name)
    {
        if (string.IsNullOrEmpty(name))
        {
            throw new ArgumentException(
                $"Invalid {kind} tool name: must not be null or empty.",
                nameof(name));
        }
        if (name == "*")
        {
            return;
        }
        if (!s_validToolName.IsMatch(name))
        {
            throw new ArgumentException(
                $"Invalid {kind} tool name '{name}': tool names must match /^[a-zA-Z0-9_-]+$/ " +
                "or be the wildcard '*'.",
                nameof(name));
        }
    }
}

/// <summary>

View on GitHub (pinned to cd8cf15dc3)