microg/GmsCore · error · IllegalArgumentException
Not a boolean type
Error message
Not a boolean type
What it means
Flag.getBool() throws IllegalArgumentException("Not a boolean type") when the flag's dataType is not DATA_TYPE_BOOL. Flag is a tagged union of primitive types, and each accessor guards its field with the type discriminator. Reading the boolean field of a non-boolean flag is rejected rather than returning a bogus default.
Source
Thrown at play-services-phenotype/src/main/java/com/google/android/gms/phenotype/Flag.java:77
}
public Flag(String name, byte[] bytesValue, int flagType) {
this.name = name;
this.bytesValue = bytesValue;
this.dataType = DATA_TYPE_BYTES;
this.flagType = flagType;
}
public long getLong() {
if (dataType == DATA_TYPE_LONG)
return longValue;
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");View on GitHub (pinned to 157c9d86ac)
Solutions
- Guard with flag.getDataType() == Flag.DATA_TYPE_BOOL before calling getBool()
- Switch over the DATA_TYPE_* constants and dispatch to the correct typed getter
- Verify the server-side flag is still defined as a boolean experiment
- Catch IllegalArgumentException at untrusted deserialization boundaries
Example fix
// before boolean enabled = flag.getBool(); // after boolean enabled = flag.getDataType() == Flag.DATA_TYPE_BOOL && flag.getBool();
Defensive patterns
Strategy: type-guard
Validate before calling
if (flag.getDataType() != Flag.DATA_TYPE_BOOL) { throw new IllegalStateException("flag is not a bool: " + flag.getDataType()); } Type guard
static boolean isBoolFlag(Flag f) { return f != null && f.getDataType() == Flag.DATA_TYPE_BOOL; } Try / catch
try { boolean v = flag.getBool(); } catch (IllegalArgumentException e) { log.warn("Flag type mismatch", e); v = DEFAULT_BOOL; } Prevention
- Check dataType == DATA_TYPE_BOOL before getBool()
- Handle all DATA_TYPE_* constants in a single switch when processing flag lists
- Re-check server flag definitions after they change type
- Default safely instead of crashing on unexpected flag types
When it happens
Trigger: Calling Flag.getBool() on a Flag whose dataType is DATA_TYPE_LONG (1), DATA_TYPE_DOUBLE (3), DATA_TYPE_STRING (4), or DATA_TYPE_BYTES (5) instead of DATA_TYPE_BOOL (2).
Common situations: Assuming all experiment flags of a given name are booleans after a server-side type change; iterating flag collections without a type switch; restoring flags from a Bundle where the type byte was lost or mis-set.
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/39d4846be91994b9.
Report an issue: GitHub.