{"record":{"id":"5243cf76c0f71727","repo":"github/copilot-sdk","slug":"tool-name-must-not-be-null-or-blank","errorCode":null,"errorMessage":"Tool name must not be null or blank","messagePattern":"Tool name must not be null or blank","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"java/sdk/src/main/java/com/github/copilot/rpc/ToolDefinition.java","lineNumber":908,"sourceCode":"            return result;\n        }\n        if (result instanceof ToolResultObject) {\n            return result;\n        }\n        try {\n            return mapper.writeValueAsString(result);\n        } catch (com.fasterxml.jackson.core.JsonProcessingException ex) {\n            throw new IllegalStateException(\"Failed to serialize tool result to JSON\", ex);\n        }\n    }\n\n    // ------------------------------------------------------------------\n    // Validation helpers\n    // ------------------------------------------------------------------\n\n    private static void requireNonBlankToolName(String name) {\n        if (name == null || name.isBlank()) {\n            throw new IllegalArgumentException(\"Tool name must not be null or blank\");\n        }\n    }\n\n    private static void requireNonBlankDescription(String description) {\n        if (description == null || description.isBlank()) {\n            throw new IllegalArgumentException(\"Tool description must not be null or blank\");\n        }\n    }\n\n    private static void requireNonNullHandler(Object handler, String toolName) {\n        if (handler == null) {\n            throw new IllegalArgumentException(\"handler must not be null for tool '\" + toolName + \"'\");\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private static List<ToolDefinition> loadDefinitions(Class<?> clazz, Object instance) {\n        String metaClassName = clazz.getName() + \"$$CopilotToolMeta\";","sourceCodeStart":890,"sourceCodeEnd":926,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/java/sdk/src/main/java/com/github/copilot/rpc/ToolDefinition.java#L890-L926","documentation":"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.","triggerScenarios":"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.","commonSituations":"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 \"\".","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."],"exampleFix":"// before\nToolDefinition.from(null, \"desc\", handler);\n\n// after\nToolDefinition.from(\"search_documents\", \"Search documents by query\", handler);","handlingStrategy":"validation","validationCode":"if (name == null || name.isBlank()) throw new IllegalArgumentException(\"tool name required\");\nToolDefinition.from(name, description, handler);","typeGuard":null,"tryCatchPattern":"try { return ToolDefinition.from(name, desc, handler); } catch (IllegalArgumentException e) {\n  log.error(\"invalid tool definition: {}\", e.getMessage()); throw e;\n}","preventionTips":["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."],"tags":["java","validation","tool-registration"],"backgroundTag":"empty-required-field","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}