github/copilot-sdk · error · IllegalArgumentException

Tool name must not be null or blank

Error message

Tool name must not be null or blank

What it means

Every Copilot tool definition requires a non-blank name, since the name is the identifier the LLM and protocol use to invoke the tool. The private helper requireNonBlankToolName rejects null or blank (whitespace-only) names with this IllegalArgumentException before a ToolDefinition is built.

Solutions

  1. Pass a non-empty descriptive tool name (letters, digits, underscores) to the from* factory method.
  2. If the name comes from config/annotations, validate it is non-blank before registering and fail fast with a clear message.
  3. Check that constants/enums supplying the name are actually initialized with the intended value.

Example fix

// before
ToolDefinition.from(null, "desc", handler);

// after
ToolDefinition.from("search_documents", "Search documents by query", handler);
Defensive patterns

Strategy: validation

Validate before calling

if (name == null || name.isBlank()) throw new IllegalArgumentException("tool name required");
ToolDefinition.from(name, description, handler);

Try / catch

try { return ToolDefinition.from(name, desc, handler); } catch (IllegalArgumentException e) {
  log.error("invalid tool definition: {}", e.getMessage()); throw e;
}

Prevention

When it happens

Trigger: Calling ToolDefinition.from/fromAsync/fromWithToolInvocation/fromAsyncWithToolInvocation with name null, "", or " " — typically because the name comes from a variable, config value, or annotation attribute that was empty.

Common situations: Building tool definitions programmatically from metadata/config where the name key is missing or empty; refactoring hardcoded names into constants and leaving them blank; annotation attributes left as "".

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/5243cf76c0f71727. Report an issue: GitHub.

Appendix: source

Thrown at java/sdk/src/main/java/com/github/copilot/rpc/ToolDefinition.java:908

            return result;
        }
        if (result instanceof ToolResultObject) {
            return result;
        }
        try {
            return mapper.writeValueAsString(result);
        } catch (com.fasterxml.jackson.core.JsonProcessingException ex) {
            throw new IllegalStateException("Failed to serialize tool result to JSON", ex);
        }
    }

    // ------------------------------------------------------------------
    // Validation helpers
    // ------------------------------------------------------------------

    private static void requireNonBlankToolName(String name) {
        if (name == null || name.isBlank()) {
            throw new IllegalArgumentException("Tool name must not be null or blank");
        }
    }

    private static void requireNonBlankDescription(String description) {
        if (description == null || description.isBlank()) {
            throw new IllegalArgumentException("Tool description must not be null or blank");
        }
    }

    private static void requireNonNullHandler(Object handler, String toolName) {
        if (handler == null) {
            throw new IllegalArgumentException("handler must not be null for tool '" + toolName + "'");
        }
    }

    @SuppressWarnings("unchecked")
    private static List<ToolDefinition> loadDefinitions(Class<?> clazz, Object instance) {
        String metaClassName = clazz.getName() + "$$CopilotToolMeta";

View on GitHub (pinned to cd8cf15dc3)