github/copilot-sdk · error · IllegalStateException
Blank or missing 'version' property in
Error message
Blank or missing 'version' property in
What it means
The native/<classifier>/platform.properties resource exists but its `version` property is blank or absent. The classifier JAR was packaged without this metadata being set, so the native package version needed for the cache path cannot be read.
Solutions
- Rebuild/replace the classifier JAR from the official release so platform.properties contains version=<native-version>.
- Inspect the artifact: unzip -p copilot-sdk-native-linux-x64.jar native/<classifier>/platform.properties.
- Purge the local Maven cache copy (~/.m2/repository/.../copilot-sdk-native-*) and re-download to rule out a corrupted artifact.
- If building the native module yourself, ensure its resource filtering writes the version property.
Example fix
// before: native/<classifier>/platform.properties inside jar version= // after (regenerate artifact) version=20241105.1
Defensive patterns
Strategy: validation
Validate before calling
try (InputStream in = getClass().getResourceAsStream("/native/" + classifier + "/platform.properties")) {
Properties p = new Properties(); p.load(in);
if (p.getProperty("version") == null || p.getProperty("version").isBlank())
throw new IllegalStateException("platform.properties in classifier JAR has no version — rebuild artifact");
}
Try / catch
try {
Path runtime = NativeRuntimeLoader.resolve();
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("Blank or missing 'version' property in native/")) {
throw new IllegalStateException("Classifier JAR is mis-packaged; replace with an official release artifact", e);
} else throw e;
} Prevention
- Use official release classifier JARs; avoid hand-built repacks.
- Verify platform.properties version is non-empty as part of artifact CI.
- Purge and re-download artifacts suspected of corruption from ~/.m2.
- If forking the native packaging, keep the version substitution step intact.
When it happens
Trigger: A hand-built or misconfigured classifier JAR where platform.properties was copied without a version value; an empty or truncated properties file inside the JAR; resource filtering for the native module skipped during its build.
Common situations: Locally rebuilt classifier JARs (mvn install on the native module with filtering broken); corrupted downloads of the classifier artifact; internal forks of the native packaging pipeline that dropped the version substitution.
Understand the failure class
Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.
Related errors
- Runtime wrapper not found on classpath: — add the matching…
- Copilot CLI executable not found at — the classifier JAR…
- Missing version resource: — ensure Maven resource…
- Native runtime metadata not found on classpath: — add the…
- 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/30331af933fd526b.
Report an issue: GitHub.
Appendix: source
Thrown at java/sdk/src/main/java/com/github/copilot/ffi/NativeRuntimeLoader.java:281
}
return version;
}
private static String readNativePackageVersion(ClassLoader loader, String classifier) throws IOException {
String resourcePath = "native/" + classifier + "/" + PLATFORM_PROPERTIES_FILENAME;
URL resource = loader.getResource(resourcePath);
if (resource == null) {
throw new FileNotFoundException("Native runtime metadata not found on classpath: " + resourcePath
+ " — add the matching classifier JAR to the classpath");
}
Properties props = new Properties();
try (InputStream in = resource.openStream()) {
props.load(in);
}
String version = props.getProperty("version");
if (version == null || version.isBlank()) {
throw new IllegalStateException("Blank or missing 'version' property in " + resourcePath);
}
return version;
}
/**
* Resolves the runtime binary path using the given parameters. Package-private
* to allow injection of test doubles in unit tests.
*/
static Path resolve(String cliPathEnv, Path cacheBase, ClassLoader loader, String classifier, String version)
throws IOException {
return resolve(cliPathEnv, cacheBase, loader, classifier, version, null, DEFAULT_PUBLISHER);
}
static Path resolve(String cliPathEnv, String bundledCliPath, Path cacheBase, ClassLoader loader, String classifier,
String version) throws IOException {
Path bundledCliDir = bundledCliPath == null ? null : Path.of(bundledCliPath).toAbsolutePath().getParent();
return resolve(cliPathEnv, cacheBase, loader, classifier, version, bundledCliDir, DEFAULT_PUBLISHER);
}View on GitHub (pinned to cd8cf15dc3)