{"record":{"id":"b884ebde48f70dee","repo":"github/copilot-sdk","slug":"native-runtime-not-found-on-classpath-add-the","errorCode":null,"errorMessage":"Native runtime not found on classpath:  — add the matching classifier JAR to the classpath","messagePattern":"Native runtime not found on classpath:  — add the matching classifier JAR to the classpath","errorType":"exception","errorClass":"FileNotFoundException","httpStatus":null,"severity":"critical","filePath":"java/sdk/src/main/java/com/github/copilot/ffi/NativeRuntimeLoader.java","lineNumber":415,"sourceCode":"            AtomicPublisher publisher, boolean extractCli) throws IOException {\n        String resourcePath = \"native/\" + classifier + \"/\" + RUNTIME_FILENAME;\n        String nativeVersion = readNativePackageVersion(loader, classifier);\n        Path cacheDir = cacheBase.resolve(version).resolve(nativeVersion).resolve(classifier);\n        Path cached = cacheDir.resolve(RUNTIME_FILENAME);\n\n        // Step 1 — fast path: return an existing valid cache entry.\n        if (isValidCachedFile(cached)) {\n            extractRuntimeAssetsToCache(cacheDir, loader, classifier, publisher);\n            if (extractCli) {\n                extractCliToCache(cacheDir, loader, classifier, publisher);\n            }\n            return cached;\n        }\n\n        // Step 2 — locate the classpath resource before creating any files.\n        URL resource = loader.getResource(resourcePath);\n        if (resource == null) {\n            throw new FileNotFoundException(\"Native runtime not found on classpath: \" + resourcePath\n                    + \" — add the matching classifier JAR to the classpath\");\n        }\n\n        // Step 3 — ensure the cache directory exists.\n        Files.createDirectories(cacheDir);\n\n        // Step 4 — write to a unique sibling temp file, then publish atomically.\n        Path temp = Files.createTempFile(cacheDir, \"runtime-tmp-\", \".node\");\n        try {\n            copyResourceToTemp(resource, resourcePath, temp);\n            publisher.publish(temp, cached);\n        } finally {\n            tryDelete(temp);\n        }\n\n        extractRuntimeAssetsToCache(cacheDir, loader, classifier, publisher);\n        if (extractCli) {\n            extractCliToCache(cacheDir, loader, classifier, publisher);","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/java/sdk/src/main/java/com/github/copilot/ffi/NativeRuntimeLoader.java#L397-L433","documentation":"extractRuntimeToCache() could not locate native/<classifier>/runtime.node on the classpath. The platform classifier JAR containing the native Node runtime binary is not present, so the loader cannot extract it to the cache directory.","triggerScenarios":"Calling NativeRuntimeLoader.resolve() with no COPILOT_CLI_PATH override and no runtime.node sibling next to any PATH-installed copilot, while the classifier JAR is missing from the classpath (extraction falls back to the bundled-CLI sibling and rethrows this error).","commonSituations":"SDK added without its platform-specific native dependency; running on a platform with no published classifier; shaded/dockerized builds stripping native/ resources; wrong classifier JAR for the detected OS/arch (e.g. linux-x64 JAR on arm64).","solutions":["Add the native classifier JAR dependency for the detected platform (same version as the SDK).","Confirm resource presence: jar tf copilot-sdk-native-*.jar | grep runtime.node.","Alternatively set COPILOT_CLI_PATH to an npm/Homebrew copilot install that has runtime.node adjacent, bypassing classpath extraction.","Match the classifier JAR to the actual runtime OS/arch reported by PlatformDetector.detectClassifier()."],"exampleFix":"// before (pom.xml): SDK only, no native artifact\n// after\n<dependency>\n  <groupId>com.github.copilot</groupId>\n  <artifactId>copilot-sdk-native</artifactId>\n  <version>1.2.0</version>\n  <classifier>linux-x64</classifier>\n</dependency>","handlingStrategy":"fallback","validationCode":"String classifier = detectClassifier();\nboolean runtimeBundled = getClass().getResourceAsStream(\"/native/\" + classifier + \"/runtime.node\") != null;\nif (!runtimeBundled && System.getenv(\"COPILOT_CLI_PATH\") == null)\n    throw new IllegalStateException(\"Neither classifier JAR nor COPILOT_CLI_PATH provides runtime.node\");\n","typeGuard":null,"tryCatchPattern":"try {\n    Path runtime = NativeRuntimeLoader.resolve();\n} catch (FileNotFoundException e) {\n    if (e.getMessage().contains(\"Native runtime not found on classpath\")) {\n        // fall back to a system-installed CLI with adjacent runtime.node\n        System.setProperty(\"COPILOT_CLI_PATH\", \"/usr/local/bin/copilot\"); // or document env setup\n        runtime = NativeRuntimeLoader.resolve();\n    } else throw e;\n}","preventionTips":["Add the native classifier dependency for every platform you deploy to.","Set COPILOT_CLI_PATH in environments without bundled classifier JARs.","Check shade/docker layer filters don't drop native/** resources.","Run a startup self-check that resolve() succeeds in each target image."],"tags":["classpath","native-loader","missing-dependency","maven"],"backgroundTag":"resource-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"}