{"record":{"id":"7d61d7371cb75930","repo":"github/copilot-sdk","slug":"copilot-cli-executable-not-found-at-the-classif","errorCode":null,"errorMessage":"Copilot CLI executable not found at  — the classifier JAR must contain both runtime.node and the copilot binary","messagePattern":"Copilot CLI executable not found at  — the classifier JAR must contain both runtime\\.node and the copilot binary","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"java/sdk/src/main/java/com/github/copilot/ffi/NativeRuntimeLoader.java","lineNumber":235,"sourceCode":"        return cachedWrapper;\n    }\n\n    static Path resolveEntrypoint(String configuredCli, Path runtimePath) throws IOException {\n        if (configuredCli != null && !configuredCli.isBlank()) {\n            Path configuredPath = Path.of(configuredCli).toAbsolutePath().normalize();\n            if (resolveFromCliPath(configuredCli) != null && Files.isRegularFile(configuredPath)\n                    && Files.size(configuredPath) > 0) {\n                return configuredPath;\n            }\n        }\n\n        Path parent = runtimePath.getParent();\n        String cliName = isWindows() ? CLI_FILENAME_WINDOWS : CLI_FILENAME;\n        Path cliPath = parent.resolve(cliName);\n        if (Files.isRegularFile(cliPath) && Files.size(cliPath) > 0) {\n            return cliPath;\n        }\n        throw new IOException(\"Copilot CLI executable not found at \" + cliPath\n                + \" — the classifier JAR must contain both runtime.node and the copilot binary\");\n    }\n\n    /**\n     * Reads the SDK version from the filtered {@code copilot-runtime.properties}\n     * resource.\n     *\n     * @return the version string\n     * @throws IOException\n     *             if the resource cannot be read\n     * @throws IllegalStateException\n     *             if the resource is missing or the version property is blank\n     */\n    static String readVersion(ClassLoader loader) throws IOException {\n        URL resource = loader.getResource(VERSION_RESOURCE);\n        if (resource == null) {\n            throw new IllegalStateException(\"Missing version resource: \" + VERSION_RESOURCE\n                    + \" — ensure Maven resource filtering has run (mvn process-resources)\");","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/java/sdk/src/main/java/com/github/copilot/ffi/NativeRuntimeLoader.java#L217-L253","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: mismatched native jar\n<dependency>\n  <artifactId>copilot-sdk-native</artifactId>\n  <version>1.0.0</version>\n  <classifier>linux-x64</classifier>\n</dependency>\n\n// after: align versions so copilot binary is bundled\n<dependency>\n  <artifactId>copilot-sdk-native</artifactId>\n  <version>1.2.0</version>\n  <classifier>linux-x64</classifier>\n</dependency>","handlingStrategy":"fallback","validationCode":"String cli = System.getenv(\"COPILOT_CLI_PATH\");\nboolean usable = cli != null && Files.isRegularFile(Path.of(cli)) && Files.size(Path.of(cli)) > 0;\nif (!usable) {\n    // ensure classifier JAR bundles the CLI before requesting the entrypoint\n    boolean bundled = getClass().getResourceAsStream(\"/native/linux-x64/copilot\") != null;\n}\n","typeGuard":null,"tryCatchPattern":"Path entrypoint;\ntry {\n    entrypoint = NativeRuntimeLoader.resolveEntrypoint();\n} catch (IOException e) {\n    if (e.getMessage().startsWith(\"Copilot CLI executable not found\")) {\n        entrypoint = installOrLocateStandaloneCopilot(); // e.g. npm install path\n    } else throw e;\n}","preventionTips":["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."],"tags":["native-loader","classpath","missing-binary","cli"],"backgroundTag":"file-not-found","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"}