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

  1. Add the native classifier JAR dependency for the detected platform (same version as the SDK).
  2. Confirm resource presence: jar tf copilot-sdk-native-*.jar | grep runtime.node.
  3. Alternatively set COPILOT_CLI_PATH to an npm/Homebrew copilot install that has runtime.node adjacent, bypassing classpath extraction.
  4. 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

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


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)