microg/GmsCore · error · IllegalArgumentException

Not a String type

Error message

Not a String type

What it means

Flag.getString() throws IllegalArgumentException("Not a String type") when the flag's dataType is not DATA_TYPE_STRING. Flag is a tagged union, and the string accessor refuses to return stringValue unless the discriminator matches, preventing silent misreads of non-string flags.

Source

Thrown at play-services-phenotype/src/main/java/com/google/android/gms/phenotype/Flag.java:89

        throw new IllegalArgumentException("Not a long type");
    }

    public boolean getBool() {
        if (dataType == DATA_TYPE_BOOL)
            return boolValue;
        throw new IllegalArgumentException("Not a boolean type");
    }

    public double getDouble() {
        if (dataType == DATA_TYPE_DOUBLE)
            return doubleValue;
        throw new IllegalArgumentException("Not a double type");
    }

    public String getString() {
        if (dataType == DATA_TYPE_STRING)
            return stringValue;
        throw new IllegalArgumentException("Not a String type");
    }

    public byte[] getBytes() {
        if (dataType == DATA_TYPE_BYTES)
            return bytesValue;
        throw new IllegalArgumentException("Not a bytes type");
    }

    public static final int DATA_TYPE_LONG = 1;
    public static final int DATA_TYPE_BOOL = 2;
    public static final int DATA_TYPE_DOUBLE = 3;
    public static final int DATA_TYPE_STRING = 4;
    public static final int DATA_TYPE_BYTES = 5;

    public static final Creator<Flag> CREATOR = findCreator(Flag.class);
}

View on GitHub (pinned to 157c9d86ac)

Solutions

  1. Guard with flag.getDataType() == Flag.DATA_TYPE_STRING before calling getString()
  2. In generic conversion code, switch over DATA_TYPE_* and convert each type to string explicitly (String.valueOf / Arrays.toString)
  3. Verify the server-side flag is still a string type
  4. Catch IllegalArgumentException when deserializing untrusted flag data

Example fix

// before
String s = flag.getString();
// after
String s = flag.getDataType() == Flag.DATA_TYPE_STRING ? flag.getString() : null;
Defensive patterns

Strategy: type-guard

Validate before calling

if (flag.getDataType() != Flag.DATA_TYPE_STRING) { throw new IllegalStateException("flag is not a string: " + flag.getDataType()); }

Type guard

static boolean isStringFlag(Flag f) { return f != null && f.getDataType() == Flag.DATA_TYPE_STRING; }

Try / catch

try { String v = flag.getString(); } catch (IllegalArgumentException e) { log.warn("Flag type mismatch", e); v = null; }

Prevention

When it happens

Trigger: Calling Flag.getString() on a Flag whose dataType is DATA_TYPE_LONG (1), DATA_TYPE_BOOL (2), DATA_TYPE_DOUBLE (3), or DATA_TYPE_BYTES (5) instead of DATA_TYPE_STRING (4).

Common situations: Treating a numeric/boolean experiment flag as a string (e.g. for feature parameters); server-side flag retyped from string to long; blanket flag-to-map conversion code that calls getString() on every entry.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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