microg/GmsCore · error · IllegalStateException
Invalid license meta-data line:
Error message
Invalid license meta-data line:
What it means
LicenseUtil.getLicensesFromMetadata parses a newline-delimited metadata string where each line is '<offset>:<length> <title>'. If a line has no space before the first position char or the position part does not split into exactly two ':'-separated values, the metadata is malformed and the method throws IllegalStateException with the offending line.
Source
Thrown at play-services-oss-licenses/src/main/java/org/microg/gms/oss/licenses/LicenseUtil.java:48
try (InputStream is = resources.openRawResource(resources.getIdentifier("third_party_licenses", "raw", context.getPackageName()))) {
if (is == null || is.available() <= 0) return false;
} catch (IOException e) {
return false;
}
return true;
}
public static List<License> getLicensesFromMetadata(Context context) {
Resources resources = context.getApplicationContext().getResources();
InputStream is = resources.openRawResource(resources.getIdentifier("third_party_license_metadata", "raw", context.getPackageName()));
String metadata = readStringAndClose(is, Integer.MAX_VALUE);
String[] lines = metadata.split("\n");
List<License> licenses = new ArrayList<>(lines.length);
for (String line : lines) {
int spaceIndex = line.indexOf(' ');
String[] position = line.substring(0, spaceIndex).split(":");
if (spaceIndex <= 0 || position.length != 2) {
throw new IllegalStateException("Invalid license meta-data line:\n" + line);
}
licenses.add(new License(line.substring(spaceIndex + 1), Long.parseLong(position[0]), Integer.parseInt(position[1]), ""));
}
return licenses;
}
public static String getLicenseText(Context context, License license) {
if (license.getPath().isEmpty()) {
Resources resources = context.getApplicationContext().getResources();
InputStream is = resources.openRawResource(resources.getIdentifier("third_party_licenses", "raw", context.getPackageName()));
try {
if (is.skip(license.getOffset()) != license.getOffset()) {
throw new RuntimeException("Failed to read license");
}
} catch (IOException e) {
throw new RuntimeException("Failed to read license", e);
}
return readStringAndClose(is, license.getLength());View on GitHub (pinned to 157c9d86ac)
Solutions
- Regenerate third_party_licenses metadata with a tool that emits '<offset>:<length> <title>' lines
- Inspect the offending line printed in the exception and fix its format (add the space, make the position 'long:int')
- Check for stray newline/empty lines or splitting bugs in the code that assembles the metadata string
Example fix
// before String line = "licenses.html MIT License"; // position not long:int // after String line = "0:1523 MIT License"; // <offset>:<length> <title>
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate each metadata line before parsing
for (String line : metadata.split("\n")) {
int spaceIndex = line.indexOf(' ');
if (spaceIndex <= 0) continue;
String[] pos = line.substring(0, spaceIndex).split(":");
if (pos.length != 2 || !pos[0].matches("\\d+") || !pos[1].matches("\\d+")) {
Log.w(TAG, "Skipping malformed metadata line: " + line);
}
} Try / catch
try {
List<License> licenses = LicenseUtil.getLicensesFromMetadata(context);
} catch (IllegalStateException e) {
Log.e(TAG, "Malformed license metadata: " + e.getMessage());
licenses = Collections.emptyList();
} Prevention
- Generate metadata with the matching microG license tool format '<offset>:<length> <title>'
- Trim stray whitespace/empty lines from the metadata string before parsing
- Pin the license-metadata generator version so format changes surface in CI
When it happens
Trigger: Calling getLicensesFromMetadata with a metadata string whose line lacks a space, or whose leading token is not 'long:int' (e.g. wrong line order, empty trailing segment, or a tool generated the metadata in a different format).
Common situations: Custom OSS-license gradle plugins or manual packaging produce metadata that differs from microG's expected format; strings files edited by hand; license metadata generated by a different (Google Play) tool version.
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
- Failed to read license
- Cannot advance the iterator beyond
- Cannot remove elements from a DataBufferIterator
- Must set attenuationBucketThresholdDb
- Must set attenuationBucketWeights
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/604d783d812bc1b2.
Report an issue: GitHub.