{"record":{"id":"e85763a23de1a589","repo":"github/copilot-sdk","slug":"clazz-must-not-be-null","errorCode":null,"errorMessage":"clazz must not be null","messagePattern":"clazz must not be null","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"java/sdk/src/main/java/com/github/copilot/rpc/ToolDefinition.java","lineNumber":314,"sourceCode":"\n    /**\n     * Discovers tool definitions from a class with static\n     * {@code @CopilotTool}-annotated methods. Requires that the\n     * {@code CopilotToolProcessor} annotation processor ran at compile time\n     * (generating the {@code $$CopilotToolMeta} companion class).\n     *\n     * @param clazz\n     *            the class containing static {@code @CopilotTool}-annotated methods\n     * @return list of tool definitions with working invocation handlers\n     * @throws IllegalStateException\n     *             if the generated {@code $$CopilotToolMeta} class is not found\n     *             (annotation processor did not run)\n     * @since 1.0.6\n     */\n    @CopilotExperimental\n    public static List<ToolDefinition> fromClass(Class<?> clazz) {\n        if (clazz == null) {\n            throw new IllegalArgumentException(\"clazz must not be null\");\n        }\n        List<String> instanceMethods = Arrays.stream(clazz.getDeclaredMethods())\n                .filter(m -> m.isAnnotationPresent(com.github.copilot.tool.CopilotTool.class))\n                .filter(m -> !Modifier.isStatic(m.getModifiers())).map(Method::getName).collect(Collectors.toList());\n        if (!instanceMethods.isEmpty()) {\n            throw new IllegalArgumentException(\n                    \"fromClass() requires all @CopilotTool methods to be static, but found instance methods: \"\n                            + instanceMethods + \". Use fromObject(new \" + clazz.getSimpleName() + \"()) instead.\");\n        }\n        return loadDefinitions(clazz, null);\n    }\n\n    // ------------------------------------------------------------------\n    // Fluent copy-style modifier methods for lambda-defined tools\n    // ------------------------------------------------------------------\n\n    /**\n     * Returns a copy with the {@code overridesBuiltInTool} flag set.","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/java/sdk/src/main/java/com/github/copilot/rpc/ToolDefinition.java#L296-L332","documentation":"Thrown by ToolDefinition.fromClass when the clazz argument is null. fromClass scans a class's declared methods for @CopilotTool annotations (without needing an instance); a null Class gives nothing to scan, so it is rejected with this IllegalArgumentException. Note fromClass also rejects classes mixing static and instance @CopilotTool methods.","triggerScenarios":"Calling ToolDefinition.fromClass(null) — e.g. Class.forName failed earlier and its result (or a caught ClassNotFoundException path) left the reference null, or a config-specified class name resolved to nothing.","commonSituations":"Config-driven tool registration where the class name string is wrong or the class isn't on the classpath; refactors deleting the tool class while registration entries remain.","solutions":["Verify the class exists and loads before calling: Class.forName(name) with exception handling, then pass its non-null result","Null-check the Class with Objects.requireNonNull(clazz) at the call site","Fix configuration/classpath so the tool class is present","Catch IllegalArgumentException at startup and report which configured class failed to register"],"exampleFix":"// before\nClass<?> c = Class.forName(cfg.toolClass); // throws elsewhere or yields null path\nToolDefinition.fromClass(c);\n// after\nClass<?> c = Class.forName(cfg.toolClass); // let CNFE surface here\nObjects.requireNonNull(c);\nToolDefinition.fromClass(c);","handlingStrategy":"validation","validationCode":"Objects.requireNonNull(clazz, \"tool class must not be null\"); Class.forName(clazz.getName());","typeGuard":"boolean canScan(Class<?> c) { return c != null; }","tryCatchPattern":"try { defs = ToolDefinition.fromClass(clazz); } catch (IllegalArgumentException e) { throw new ToolRegistrationException(String.valueOf(clazz), e); }","preventionTips":["Resolve configured class names with Class.forName and handle ClassNotFoundException explicitly","Remove registration entries for deleted tool classes","Null-check configuration-derived Class references before scanning"],"tags":["java","null-argument","tool-registration","reflection"],"backgroundTag":"null-argument","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"}