github/copilot-sdk · error · IOException
Invalid runtime asset inventory entry:
Error message
Invalid runtime asset inventory entry:
What it means
A line in the runtime-assets.list inventory resource did not split into exactly two tab-separated fields (octal mode and relative path). The loader treats the inventory as a strict manifest for extracting extra runtime assets, so a malformed line aborts extraction to avoid silently skipping assets.
Solutions
- Replace the classifier JAR with an official release artifact whose runtime-assets.list is well-formed (mode<TAB>path per line).
- Inspect the manifest: unzip -p copilot-sdk-native-*.jar native/<classifier>/runtime-assets.list and check each line has exactly one tab.
- If building the JAR yourself, fix the manifest generation step to emit tab-separated mode and path fields.
- Purge the cached/local Maven copy and re-download to rule out artifact corruption.
Example fix
// before: runtime-assets.list (malformed) 0755 assets/node_modules/module.js 0755 extra/tool // after (mode<TAB>relative path, one per line) 0755 assets/node_modules/module.js 0755 extra/tool
Defensive patterns
Strategy: validation
Validate before calling
try (BufferedReader r = new BufferedReader(new InputStreamReader(
getClass().getResourceAsStream("/native/" + classifier + "/runtime-assets.list"), UTF_8))) {
String line;
while ((line = r.readLine()) != null)
if (!line.isBlank() && line.split("\t", -1).length < 2)
throw new IllegalStateException("Malformed runtime-assets.list entry: " + line);
}
Try / catch
try {
Path runtime = NativeRuntimeLoader.resolve();
} catch (IOException e) {
if (e.getMessage().startsWith("Invalid runtime asset inventory entry")) {
throw new IllegalStateException("Classifier JAR manifest is corrupt; replace with an official artifact", e);
} else throw e;
} Prevention
- Use official classifier JAR artifacts; don't regenerate resources manually.
- Keep runtime-assets.list strictly tab-separated with one entry per line (LF endings).
- Validate the manifest as part of the native packaging CI.
- Re-download artifacts if a build suddenly starts failing with inventory errors.
When it happens
Trigger: Calling resolve()/extractToCache() with a classifier JAR whose runtime-assets.list is corrupted, hand-edited, line-wrapped by a text editor, or uses spaces/newlines instead of tabs as separators.
Common situations: Locally regenerated classifier JARs where the manifest was written with spaces or CRLF-joined fields; a build step that re-formatted or minified resource files; truncated download of the classifier artifact.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Runtime wrapper not found on classpath: — add the matching…
- Copilot CLI executable not found at — the classifier JAR…
- Native runtime metadata not found on classpath: — add the…
- Blank or missing 'version' property in
- Native runtime not found on classpath: — add the matching…
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/c3a39088d632c07a.
Report an issue: GitHub.
Appendix: source
Thrown at java/sdk/src/main/java/com/github/copilot/ffi/NativeRuntimeLoader.java:456
private static void extractRuntimeAssetsToCache(Path cacheDir, ClassLoader loader, String classifier,
AtomicPublisher publisher) throws IOException {
String inventoryResourcePath = "native/" + classifier + "/" + RUNTIME_ASSETS_FILENAME;
URL inventoryResource = loader.getResource(inventoryResourcePath);
if (inventoryResource == null) {
return;
}
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(inventoryResource.openStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
if (line.isBlank()) {
continue;
}
String[] fields = line.split("\\t", 2);
if (fields.length != 2) {
throw new IOException("Invalid runtime asset inventory entry: " + line);
}
boolean executable = (Integer.parseInt(fields[0], 8) & 0111) != 0;
Path relative = Path.of(fields[1]).normalize();
if (relative.isAbsolute() || relative.startsWith("..")) {
throw new IOException("Unsafe runtime asset inventory path: " + fields[1]);
}
Path cached = cacheDir.resolve(relative).normalize();
if (!cached.startsWith(cacheDir)) {
throw new IOException("Runtime asset escapes cache directory: " + fields[1]);
}
if (isValidCachedFile(cached) && (!executable || isWindows() || Files.isExecutable(cached))) {
continue;
}
String resourcePath = "native/" + classifier + "/" + fields[1];
URL resource = loader.getResource(resourcePath);
if (resource == null) {
throw new FileNotFoundException("Runtime asset not found on classpath: " + resourcePath);View on GitHub (pinned to cd8cf15dc3)