github/copilot-sdk · error · IOException
Copilot CLI executable not found at — the classifier JAR…
Error message
Copilot CLI executable not found at — the classifier JAR must contain both runtime.node and the copilot binary
What it means
resolveEntrypoint() located the extracted runtime.node but could not find a non-empty copilot (copilot.exe on Windows) executable in the same directory. The classifier JAR is expected to bundle both the native runtime and the legacy CLI entrypoint; only the runtime was found.
Solutions
- Upgrade the platform classifier JAR to the same version as the SDK so it bundles both runtime.node and the copilot binary.
- Verify the JAR contents: jar tf copilot-sdk-native-*.jar | grep 'copilot$' (or copilot.exe).
- Set COPILOT_CLI_PATH to an explicitly installed copilot CLI that has a compatible runtime.node adjacent (flat layout or prebuilds/<classifier>).
- If you don't need legacy entrypoint hosting, avoid calling resolveEntrypoint() and use the standard runtime path.
Example fix
// before: mismatched native jar <dependency> <artifactId>copilot-sdk-native</artifactId> <version>1.0.0</version> <classifier>linux-x64</classifier> </dependency> // after: align versions so copilot binary is bundled <dependency> <artifactId>copilot-sdk-native</artifactId> <version>1.2.0</version> <classifier>linux-x64</classifier> </dependency>
Defensive patterns
Strategy: fallback
Validate before calling
String cli = System.getenv("COPILOT_CLI_PATH");
boolean usable = cli != null && Files.isRegularFile(Path.of(cli)) && Files.size(Path.of(cli)) > 0;
if (!usable) {
// ensure classifier JAR bundles the CLI before requesting the entrypoint
boolean bundled = getClass().getResourceAsStream("/native/linux-x64/copilot") != null;
}
Try / catch
Path entrypoint;
try {
entrypoint = NativeRuntimeLoader.resolveEntrypoint();
} catch (IOException e) {
if (e.getMessage().startsWith("Copilot CLI executable not found")) {
entrypoint = installOrLocateStandaloneCopilot(); // e.g. npm install path
} else throw e;
} Prevention
- Keep the native classifier JAR and SDK versions aligned so the CLI binary is bundled.
- If using COPILOT_CLI_PATH, point at a full installation layout (runtime.node sibling or prebuilds/), not a lone copied binary.
- Only request the legacy entrypoint when legacy hosting is actually needed.
- Verify JAR contents (copilot binary present) in CI as a build check.
When it happens
Trigger: Calling NativeRuntimeLoader.resolveEntrypoint() (directly or via the SDK) with a classifier JAR that contains native/<classifier>/runtime.node but not native/<classifier>/copilot; or COPILOT_CLI_PATH pointing at a CLI without an adjacent valid runtime, then falling back to the cache dir which lacks the CLI.
Common situations: Classifier JAR version mismatch with the SDK (older JAR predates CLI bundling); slimmed-down native artifact; COPILOT_CLI_PATH pointing to a copy of the binary without siblings; legacy extension hosting requested on a platform JAR that never shipped the CLI.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Runtime wrapper not found on classpath: — add the matching…
- Native runtime metadata not found on classpath: — add the…
- Blank or missing 'version' property in
- Native runtime not found on classpath: — add the matching…
- Invalid runtime asset inventory entry:
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/7d61d7371cb75930.
Report an issue: GitHub.
Appendix: source
Thrown at java/sdk/src/main/java/com/github/copilot/ffi/NativeRuntimeLoader.java:235
return cachedWrapper;
}
static Path resolveEntrypoint(String configuredCli, Path runtimePath) throws IOException {
if (configuredCli != null && !configuredCli.isBlank()) {
Path configuredPath = Path.of(configuredCli).toAbsolutePath().normalize();
if (resolveFromCliPath(configuredCli) != null && Files.isRegularFile(configuredPath)
&& Files.size(configuredPath) > 0) {
return configuredPath;
}
}
Path parent = runtimePath.getParent();
String cliName = isWindows() ? CLI_FILENAME_WINDOWS : CLI_FILENAME;
Path cliPath = parent.resolve(cliName);
if (Files.isRegularFile(cliPath) && Files.size(cliPath) > 0) {
return cliPath;
}
throw new IOException("Copilot CLI executable not found at " + cliPath
+ " — the classifier JAR must contain both runtime.node and the copilot binary");
}
/**
* Reads the SDK version from the filtered {@code copilot-runtime.properties}
* resource.
*
* @return the version string
* @throws IOException
* if the resource cannot be read
* @throws IllegalStateException
* if the resource is missing or the version property is blank
*/
static String readVersion(ClassLoader loader) throws IOException {
URL resource = loader.getResource(VERSION_RESOURCE);
if (resource == null) {
throw new IllegalStateException("Missing version resource: " + VERSION_RESOURCE
+ " — ensure Maven resource filtering has run (mvn process-resources)");View on GitHub (pinned to cd8cf15dc3)