github/copilot-sdk · error · IllegalStateException

Failed to invoke + metaClassName + .definitions()

Error message

Failed to invoke  + metaClassName + .definitions()

What it means

After locating the generated $$CopilotToolMeta class, loadDefinitions instantiates it and calls its definitions() method reflectively. Any ReflectiveOperationException during that step (constructor not accessible, instantiation failure, invocation error) is wrapped in this IllegalStateException. Unlike error 225, the metadata class exists but could not be constructed or invoked.

Solutions

  1. Run a clean rebuild so generated metadata and SDK version are in sync.
  2. Align the copilot-sdk-java version used at compile time (processor) and runtime in all modules.
  3. Check the cause (ex.getCause()) — if the meta-class constructor threw, fix the underlying initialization error in the tool class.
  4. Verify the tool classes' jar actually contains the freshly generated meta classes and is not a stale artifact.

Example fix

// before (build.gradle)
implementation 'com.github.copilot:copilot-sdk-java:1.0.0'
// lib module still compiles against 0.9.0 → stale meta class

// after (build.gradle)
// same version everywhere
def copilotSdk = 'com.github.copilot:copilot-sdk-java:1.2.0'
implementation copilotSdk
annotationProcessor copilotSdk
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure compile & runtime SDK versions match in the build script before registration

Try / catch

try { defs = ToolDefinition.fromObject(new Tools()); }
catch (IllegalStateException e) {
  log.error("failed to invoke generated metadata for {}", e.getCause(), e);
  throw e;
}

Prevention

When it happens

Trigger: The generated meta class exists but its no-arg constructor fails (e.g. its own initialization throws), the class was compiled against an incompatible SDK version so definitions() has an unexpected signature, or classloader/visibility issues prevent instantiation.

Common situations: Mixing SDK versions: tool classes compiled against an older copilot-sdk-java but running with a newer SDK (or vice versa) so the generated code's expected interface changed; hot-swap/incremental recompiles leaving stale generated classes; classloader isolation in app servers preventing instantiation.

Related errors


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

Appendix: source

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

        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";
        try {
            Class<?> metaClass = Class.forName(metaClassName, true, clazz.getClassLoader());
            var provider = (com.github.copilot.tool.CopilotToolMetadataProvider<Object>) metaClass
                    .getDeclaredConstructor().newInstance();
            return provider.definitions(instance, getConfiguredMapper());
        } catch (ClassNotFoundException e) {
            throw new IllegalStateException("Generated class " + metaClassName + " not found. "
                    + "Ensure the CopilotToolProcessor annotation processor ran during compilation. "
                    + "Add the copilot-sdk-java dependency to your annotation processor path.", e);
        } catch (ReflectiveOperationException e) {
            throw new IllegalStateException("Failed to invoke " + metaClassName + ".definitions()", e);
        }
    }

    /**
     * Returns the SDK-configured ObjectMapper for tool argument/result
     * serialization. Configuration mirrors
     * {@code JsonRpcClient.createObjectMapper()}.
     */
    private static ObjectMapper getConfiguredMapper() {
        return ConfiguredMapperHolder.INSTANCE;
    }

    /**
     * Lazy holder for the configured ObjectMapper (thread-safe, initialized on
     * first access).
     */
    private static final class ConfiguredMapperHolder {
        static final ObjectMapper INSTANCE = createMapper();

View on GitHub (pinned to cd8cf15dc3)