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
- Pass a non-empty descriptive tool name (letters, digits, underscores) to the from* factory method.
- If the name comes from config/annotations, validate it is non-blank before registering and fail fast with a clear message.
- 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
- Define tool names as compile-time constants, never inline empty strings.
- Fail fast on config loading when a tool name field is missing/blank.
- Code-review every from* call for name presence.
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
- Tool description must not be null or blank
- handler must not be null for tool ' + toolName + '
- CliUrl is mutually exclusive with CliPath
- TcpConnectionToken must be a non-empty string
- Invalid value ' '. Expected 'inprocess', 'stdio', or unset.
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)