{"record":{"id":"be714c1cfe25741e","repo":"prestodb/presto","slug":"unexpected-type","errorCode":null,"errorMessage":"Unexpected type: ","messagePattern":"Unexpected type: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"presto-parquet/src/main/java/com/facebook/presto/parquet/spark/VariantUtil.java","lineNumber":245,"sourceCode":"                        return Type.DOUBLE;\n                    case DECIMAL4:\n                    case DECIMAL8:\n                    case DECIMAL16:\n                        return Type.DECIMAL;\n                    case DATE:\n                        return Type.DATE;\n                    case TIMESTAMP:\n                        return Type.TIMESTAMP;\n                    case TIMESTAMP_NTZ:\n                        return Type.TIMESTAMP_NTZ;\n                    case FLOAT:\n                        return Type.FLOAT;\n                    case BINARY:\n                        return Type.BINARY;\n                    case LONG_STR:\n                        return Type.STRING;\n                    default:\n                        throw new IllegalArgumentException(\"Unexpected type: \" + typeInfo);\n                }\n        }\n    }\n\n    private static IllegalStateException unexpectedType(Type type)\n    {\n        return new IllegalStateException(\"Expect type to be \" + type);\n    }\n\n    // Get a boolean value from variant value `value[position...]`.\n    // Throw `MALFORMED_VARIANT` if the variant is malformed.\n    public static boolean getBoolean(byte[] value, int position)\n    {\n        checkIndex(position, value.length);\n        int basicType = value[position] & BASIC_TYPE_MASK;\n        int typeInfo = (value[position] >> BASIC_TYPE_BITS) & TYPE_INFO_MASK;\n        if (basicType != PRIMITIVE || (typeInfo != TRUE && typeInfo != FALSE)) {\n            throw unexpectedType(Type.BOOLEAN);","sourceCodeStart":227,"sourceCodeEnd":263,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-parquet/src/main/java/com/facebook/presto/parquet/spark/VariantUtil.java#L227-L263","documentation":"VariantUtil.getType decodes the Variant binary encoding: it reads the header byte at `position`, splits it into a basic type (low bits) and type-info (high bits), and maps the primitive type-info codes to a Type enum. This IllegalArgumentException is the MALFORMED_VARIANT guard thrown from the `default` branch when the type-info bits encode a value this library does not recognize — either the variant binary is corrupt/truncated or it was produced by a writer using a newer type code this reader does not know.","triggerScenarios":"Calling VariantUtil.getType(byte[] value, int position) on a variant value whose header byte has basicType == PRIMITIVE but a typeInfo code not in the known set (NULL, TRUE/FALSE, INT1/2/4/8, DOUBLE, DECIMAL4/8/16, DATE, TIMESTAMP, TIMESTAMP_NTZ, FLOAT, BINARY, LONG_STR), typically because the bytes are corrupted or written by a newer Spark Variant spec.","commonSituations":"Reading Parquet files with variant columns written by a newer Spark/other-engine version that added type codes; corrupted or hand-crafted variant byte arrays; passing the wrong byte[] or a non-variant blob to getType.","solutions":["Verify the producer and consumer use compatible Variant binary spec versions; upgrade the presto-parquet reader to match the writer","Re-read the source Parquet file / regenerate the variant data to rule out corruption","Validate the variant byte array (header byte, offsets, lengths) before calling getType","Catch IllegalArgumentException from getType and treat the value as malformed rather than crashing the read"],"exampleFix":"// before\nType t = VariantUtil.getType(value, pos);\n// after\nType t;\ntry {\n    t = VariantUtil.getType(value, pos);\n} catch (IllegalArgumentException e) {\n    t = Type.NULL; // or surface a corrupt-row metric\n}","handlingStrategy":"try-catch","validationCode":"// Java\nstatic boolean looksLikeKnownVariantType(byte[] value, int position) {\n    if (position < 0 || position >= value.length) return false;\n    int basicType = value[position] & 0x3;\n    if (basicType == 0x1 || basicType == 0x2 || basicType == 0x3) return true; // SHORT_STR/OBJECT/ARRAY\n    int typeInfo = (value[position] >> 2) & 0x3f;\n    return typeInfo <= 15; // all known primitive type codes are contiguous low values\n}","typeGuard":"// Java\nstatic boolean isReadableVariant(byte[] value, int position) {\n    try { VariantUtil.getType(value, position); return true; }\n    catch (RuntimeException e) { return false; }\n}","tryCatchPattern":"// Java\ntry {\n    Type t = VariantUtil.getType(value, pos);\n    // use t\n} catch (IllegalArgumentException e) {\n    log.warn(\"Malformed variant type at pos \" + pos, e);\n    // skip row / mark corrupt\n}","preventionTips":["Keep the Parquet reader and the variant-producing engine on compatible versions","Validate variant header bytes before interpreting values","Treat IllegalArgumentException from VariantUtil as malformed-data, not a code bug","Add metrics for malformed variant rows to detect producer regressions early"],"tags":["variant","malformed-data","parquet","illegal-argument"],"backgroundTag":"malformed-variant-binary","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}