microg/GmsCore · error · IllegalArgumentException
Not a long type
Error message
Not a long type
What it means
Flag.getLong() throws IllegalArgumentException("Not a long type") when the flag's dataType is not DATA_TYPE_LONG. The phenotype Flag class stores several differently-typed values (long, bool, double, string, bytes) and each typed getter validates the flag's type discriminator before returning the field. Calling a getter that does not match the flag's actual type is treated as a programming error and fails fast.
Source
Thrown at play-services-phenotype/src/main/java/com/google/android/gms/phenotype/Flag.java:71
public Flag(String name, String stringValue, int flagType) {
this.name = name;
this.stringValue = stringValue;
this.dataType = DATA_TYPE_STRING;
this.flagType = flagType;
}
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");View on GitHub (pinned to 157c9d86ac)
Solutions
- Check flag.getDataType() (or flagType) before calling the getter and route to the matching getBool/getDouble/getString/getBytes
- Add a switch/case over the DATA_TYPE_* constants that handles LONG and skips or defaults for other types
- If the flag should always be long, verify the server-side experiment configuration hasn't changed the flag's type
- Wrap the call in try-catch (IllegalArgumentException) only at boundaries where flag provenance is untrusted
Example fix
// before long value = flag.getLong(); // after long value = flag.getDataType() == Flag.DATA_TYPE_LONG ? flag.getLong() : 0L;
Defensive patterns
Strategy: type-guard
Validate before calling
if (flag.getDataType() != Flag.DATA_TYPE_LONG) { throw new IllegalStateException("flag is not a long: " + flag.getDataType()); } Type guard
static boolean isLongFlag(Flag f) { return f != null && f.getDataType() == Flag.DATA_TYPE_LONG; } Try / catch
try { long v = flag.getLong(); } catch (IllegalArgumentException e) { log.warn("Flag type mismatch", e); v = DEFAULT_LONG; } Prevention
- Always switch on flag.getDataType() before accessing a typed getter
- Do not assume a flag's type is stable across server-side experiment updates
- Centralize flag decoding in one helper that dispatches per DATA_TYPE_* constant
- Log the flag name and dataType when a getter is rejected
When it happens
Trigger: Calling Flag.getLong() on a Flag whose dataType is DATA_TYPE_BOOL (2), DATA_TYPE_DOUBLE (3), DATA_TYPE_STRING (4), or DATA_TYPE_BYTES (5) instead of DATA_TYPE_LONG (1). Typically happens when iterating a heterogeneous list of Flags and blindly casting/calling getLong() on each.
Common situations: Iterating server-fetched phenotype flags without switching on flagType/dataType; a server experiment changed a flag's type from long to boolean; deserializing flags from a Bundle or proto where the type constant was set by another code path; copy-pasted getter calls across flag refactors.
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
- Not a boolean type
- Not a double type
- Not a String type
- Not a bytes type
- remoteBinder is the wrong class.
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/49d06e690ad3fd34.
Report an issue: GitHub.