{"record":{"id":"ca4434d18fb07299","repo":"prestodb/presto","slug":"index-out-of-bound-s-size-s","errorCode":null,"errorMessage":"Index out of bound: %s (size: %s)","messagePattern":"Index out of bound: (.+?) \\(size: (.+?)\\)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"presto-parquet/src/main/java/com/facebook/presto/parquet/spark/VariantUtil.java","lineNumber":497,"sourceCode":"        // Extracts b1b0 to determine the integer size of the offset list.\n        int offsetSize = (typeInfo & 0x3) + 1;\n        int offsetStart = position + 1 + sizeBytes;\n        int dataStart = offsetStart + (size + 1) * offsetSize;\n        return handler.apply(size, offsetSize, offsetStart, dataStart);\n    }\n\n    // Get a key at `id` in the variant metadata.\n    // Throw `MALFORMED_VARIANT` if the variant is malformed. An out-of-bound `id` is also considered\n    // a malformed variant because it is read from the corresponding variant value.\n    public static String getMetadataKey(byte[] metadata, int id)\n    {\n        checkIndex(0, metadata.length);\n        // Extracts the highest 2 bits in the metadata header to determine the integer size of the\n        // offset list.\n        int offsetSize = ((metadata[0] >> 6) & 0x3) + 1;\n        int dictSize = readUnsigned(metadata, 1, offsetSize);\n        if (id >= dictSize) {\n            throw new IllegalArgumentException(String.format(\"Index out of bound: %s (size: %s)\", id, dictSize));\n        }\n        // There are a header byte, a `dictSize` with `offsetSize` bytes, and `(dictSize + 1)` offsets\n        // before the string data.\n        int stringStart = 1 + (dictSize + 2) * offsetSize;\n        int offset = readUnsigned(metadata, 1 + (id + 1) * offsetSize, offsetSize);\n        int nextOffset = readUnsigned(metadata, 1 + (id + 2) * offsetSize, offsetSize);\n        if (offset > nextOffset) {\n            throw new IllegalArgumentException(String.format(\"Invalid offset: %s > %s\", offset, nextOffset));\n        }\n        checkIndex(stringStart + nextOffset - 1, metadata.length);\n        return new String(metadata, stringStart + offset, nextOffset - offset, UTF_8);\n    }\n}\n","sourceCodeStart":479,"sourceCodeEnd":511,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-parquet/src/main/java/com/facebook/presto/parquet/spark/VariantUtil.java#L479-L511","documentation":"This is thrown by the Variant metadata/dictionary accessor in VariantUtil: the metadata header's first two bits give the offset-size, the next bytes give the dictionary size (dictSize), and `id` must be a valid index into that dictionary. This IllegalArgumentException is raised when the requested variant dictionary id is >= dictSize, i.e. the caller asked for a string key that does not exist in the variant's metadata dictionary — normally a sign of malformed variant bytes or a misread offset.","triggerScenarios":"Resolving an object field or array element in a Variant whose field-id `id` (read from the value's object header) is greater than or equal to the dictSize parsed from the metadata header — happens when value and metadata arrays do not belong together, or the metadata bytes are corrupt.","commonSituations":"Pairing a variant value[] from one row with a metadata[] from another; corrupted Parquet variant columns; writers that violate the Variant metadata layout so dictSize is parsed wrong.","solutions":["Ensure the value[] and metadata[] byte arrays passed together come from the same variant cell","Validate the metadata header (offsetSize, dictSize) before indexing and reject inconsistent pairs","Re-read/regenerate the source Parquet data to rule out corruption","Catch IllegalArgumentException and treat the variant object as malformed"],"exampleFix":"// before\nString key = VariantUtil.getMetadataString(metadata, fieldId);\n// after\ntry {\n    String key = VariantUtil.getMetadataString(metadata, fieldId);\n} catch (IllegalArgumentException e) {\n    throw new IllegalArgumentException(\"Field id out of variant dictionary bounds: \" + fieldId, e);\n}","handlingStrategy":"validation","validationCode":"// Java\nstatic boolean isIdInDictionary(byte[] metadata, int id) {\n    if (metadata == null || metadata.length == 0) return false;\n    int offsetSize = ((metadata[0] >> 6) & 0x3) + 1;\n    int dictSize = VariantUtil.readUnsigned(metadata, 1, offsetSize);\n    return id >= 0 && id < dictSize;\n}","typeGuard":null,"tryCatchPattern":"// Java\ntry {\n    String key = VariantUtil.getMetadataString(metadata, id);\n} catch (IllegalArgumentException e) {\n    // value/metadata mismatch or corrupt metadata: skip the row\n}","preventionTips":["Always pass the value[] and metadata[] arrays from the same variant cell","Check that offsetSize/dictSize parsed from the header are consistent with metadata.length","Detect producer/consumer version mismatches in the Variant spec","Handle per-row corrupt variants gracefully rather than aborting the query"],"tags":["variant","index-out-of-bounds","malformed-data","parquet"],"backgroundTag":"variant-dictionary-index-out-of-bounds","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"}