{"record":{"id":"0c2d41e21ad9762a","repo":"microg/GmsCore","slug":"not-a-bytes-type","errorCode":null,"errorMessage":"Not a bytes type","messagePattern":"Not a bytes type","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"play-services-phenotype/src/main/java/com/google/android/gms/phenotype/Flag.java","lineNumber":95,"sourceCode":"        throw new IllegalArgumentException(\"Not a boolean type\");\n    }\n\n    public double getDouble() {\n        if (dataType == DATA_TYPE_DOUBLE)\n            return doubleValue;\n        throw new IllegalArgumentException(\"Not a double type\");\n    }\n\n    public String getString() {\n        if (dataType == DATA_TYPE_STRING)\n            return stringValue;\n        throw new IllegalArgumentException(\"Not a String type\");\n    }\n\n    public byte[] getBytes() {\n        if (dataType == DATA_TYPE_BYTES)\n            return bytesValue;\n        throw new IllegalArgumentException(\"Not a bytes type\");\n    }\n\n    public static final int DATA_TYPE_LONG = 1;\n    public static final int DATA_TYPE_BOOL = 2;\n    public static final int DATA_TYPE_DOUBLE = 3;\n    public static final int DATA_TYPE_STRING = 4;\n    public static final int DATA_TYPE_BYTES = 5;\n\n    public static final Creator<Flag> CREATOR = findCreator(Flag.class);\n}\n","sourceCodeStart":77,"sourceCodeEnd":106,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-phenotype/src/main/java/com/google/android/gms/phenotype/Flag.java#L77-L106","documentation":"Flag.getBytes() throws IllegalArgumentException(\"Not a bytes type\") when the flag's dataType is not DATA_TYPE_BYTES. The bytes accessor validates the dataType discriminator before returning bytesValue; reading byte-array content from any other kind of flag is rejected as a caller bug.","triggerScenarios":"Calling Flag.getBytes() on a Flag whose dataType is DATA_TYPE_LONG (1), DATA_TYPE_BOOL (2), DATA_TYPE_DOUBLE (3), or DATA_TYPE_STRING (4) instead of DATA_TYPE_BYTES (5).","commonSituations":"Assuming a binary/certificate-style flag is stored as bytes when the server defines it as a string; generic flag iteration that calls getBytes() unconditionally; confusion between string and bytes flags after a server config change.","solutions":["Guard with flag.getDataType() == Flag.DATA_TYPE_BYTES before calling getBytes()","If the flag may be a string, fall back to flag.getString().getBytes(StandardCharsets.UTF_8)","Switch over DATA_TYPE_* constants and handle the BYTES case explicitly","Verify the server-side flag is defined as a bytes/bytearray type"],"exampleFix":"// before\nbyte[] raw = flag.getBytes();\n// after\nbyte[] raw = flag.getDataType() == Flag.DATA_TYPE_BYTES\n    ? flag.getBytes()\n    : flag.getString().getBytes(StandardCharsets.UTF_8);","handlingStrategy":"type-guard","validationCode":"if (flag.getDataType() != Flag.DATA_TYPE_BYTES) { throw new IllegalStateException(\"flag is not bytes: \" + flag.getDataType()); }","typeGuard":"static boolean isBytesFlag(Flag f) { return f != null && f.getDataType() == Flag.DATA_TYPE_BYTES; }","tryCatchPattern":"try { byte[] v = flag.getBytes(); } catch (IllegalArgumentException e) { log.warn(\"Flag type mismatch\", e); v = EMPTY_BYTES; }","preventionTips":["Check dataType == DATA_TYPE_BYTES before getBytes()","Convert string flags explicitly with a named charset instead of assuming bytes","Confirm binary flags are serialized as byte arrays end-to-end","Handle DATA_TYPE_* exhaustively in flag decoding code"],"tags":["android","phenotype","type-mismatch","flags"],"backgroundTag":"type-mismatch","analyzedSha":"157c9d86ac46c195a86c2f15ab55c84036223f95","analyzedAt":"2026-09-06T17:27:33.892Z","contentChangedAt":"2026-09-06T17:27:33.892Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}