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

  1. Regenerate third_party_licenses metadata with a tool that emits '<offset>:<length> <title>' lines
  2. Inspect the offending line printed in the exception and fix its format (add the space, make the position 'long:int')
  3. 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

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


AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06). Data as JSON: /api/errors/604d783d812bc1b2. Report an issue: GitHub.