github/copilot-sdk · critical · FileNotFoundException
Native runtime not found on classpath: — add the matching…
Error message
Native runtime not found on classpath: — add the matching classifier JAR to the classpath
What it means
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.
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().
Example fix
// before (pom.xml): SDK only, no native artifact // after <dependency> <groupId>com.github.copilot</groupId> <artifactId>copilot-sdk-native</artifactId> <version>1.2.0</version> <classifier>linux-x64</classifier> </dependency>
Defensive patterns
Strategy: fallback
Validate before calling
String classifier = detectClassifier();
boolean runtimeBundled = getClass().getResourceAsStream("/native/" + classifier + "/runtime.node") != null;
if (!runtimeBundled && System.getenv("COPILOT_CLI_PATH") == null)
throw new IllegalStateException("Neither classifier JAR nor COPILOT_CLI_PATH provides runtime.node");
Try / catch
try {
Path runtime = NativeRuntimeLoader.resolve();
} catch (FileNotFoundException e) {
if (e.getMessage().contains("Native runtime not found on classpath")) {
// fall back to a system-installed CLI with adjacent runtime.node
System.setProperty("COPILOT_CLI_PATH", "/usr/local/bin/copilot"); // or document env setup
runtime = NativeRuntimeLoader.resolve();
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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).
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Runtime wrapper not found on classpath: — add the matching…
- Native runtime metadata not found on classpath: — add the…
- Copilot CLI executable not found at — the classifier JAR…
- Missing version resource: — ensure Maven resource…
- Blank or missing 'version' property in
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/b884ebde48f70dee.
Report an issue: GitHub.
Appendix: source
Thrown at java/sdk/src/main/java/com/github/copilot/ffi/NativeRuntimeLoader.java:415
AtomicPublisher publisher, boolean extractCli) throws IOException {
String resourcePath = "native/" + classifier + "/" + RUNTIME_FILENAME;
String nativeVersion = readNativePackageVersion(loader, classifier);
Path cacheDir = cacheBase.resolve(version).resolve(nativeVersion).resolve(classifier);
Path cached = cacheDir.resolve(RUNTIME_FILENAME);
// Step 1 — fast path: return an existing valid cache entry.
if (isValidCachedFile(cached)) {
extractRuntimeAssetsToCache(cacheDir, loader, classifier, publisher);
if (extractCli) {
extractCliToCache(cacheDir, loader, classifier, publisher);
}
return cached;
}
// Step 2 — locate the classpath resource before creating any files.
URL resource = loader.getResource(resourcePath);
if (resource == null) {
throw new FileNotFoundException("Native runtime not found on classpath: " + resourcePath
+ " — add the matching classifier JAR to the classpath");
}
// Step 3 — ensure the cache directory exists.
Files.createDirectories(cacheDir);
// Step 4 — write to a unique sibling temp file, then publish atomically.
Path temp = Files.createTempFile(cacheDir, "runtime-tmp-", ".node");
try {
copyResourceToTemp(resource, resourcePath, temp);
publisher.publish(temp, cached);
} finally {
tryDelete(temp);
}
extractRuntimeAssetsToCache(cacheDir, loader, classifier, publisher);
if (extractCli) {
extractCliToCache(cacheDir, loader, classifier, publisher);View on GitHub (pinned to cd8cf15dc3)