{"record":{"id":"63f44a7f81053404","repo":"prestodb/presto","slug":"newdictionary-must-have-the-same-position-count","errorCode":null,"errorMessage":"newDictionary must have the same position count","messagePattern":"newDictionary must have the same position count","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"presto-common/src/main/java/com/facebook/presto/common/block/DictionaryBlock.java","lineNumber":514,"sourceCode":"    {\n        return format(\"DictionaryBlock(%d){positionCount=%d,dictionary=%s}\", hashCode(), getPositionCount(), dictionary.toString());\n    }\n\n    @Override\n    public Block getLoadedBlock()\n    {\n        Block loadedDictionary = dictionary.getLoadedBlock();\n\n        if (loadedDictionary == dictionary) {\n            return this;\n        }\n        return new DictionaryBlock(idsOffset, getPositionCount(), loadedDictionary, ids, false, randomDictionaryId());\n    }\n\n    public Block createProjection(Block newDictionary)\n    {\n        if (newDictionary.getPositionCount() != dictionary.getPositionCount()) {\n            throw new IllegalArgumentException(\"newDictionary must have the same position count\");\n        }\n\n        // if the new dictionary is lazy be careful to not materialize it\n        if (newDictionary instanceof LazyBlock) {\n            return new LazyBlock(positionCount, (block) -> {\n                Block newDictionaryBlock = newDictionary.getBlock(0);\n                Block newBlock = createProjection(newDictionaryBlock);\n                block.setBlock(newBlock);\n            });\n        }\n        if (newDictionary instanceof RunLengthEncodedBlock) {\n            RunLengthEncodedBlock rle = (RunLengthEncodedBlock) newDictionary;\n            return new RunLengthEncodedBlock(rle.getValue(), positionCount);\n        }\n\n        // unwrap dictionary in dictionary\n        int[] newIds = new int[positionCount];\n        for (int position = 0; position < positionCount; position++) {","sourceCodeStart":496,"sourceCodeEnd":532,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-common/src/main/java/com/facebook/presto/common/block/DictionaryBlock.java#L496-L532","documentation":"DictionaryBlock.createProjection replaces the block's dictionary with a new one while keeping the same id array. This only works if the new dictionary has exactly the same number of positions as the old one, since the existing ids index directly into it. The library throws IllegalArgumentException when the position counts differ, because otherwise ids could point past the end of the new dictionary.","triggerScenarios":"Calling DictionaryBlock.createProjection(newDictionary) where newDictionary.getPositionCount() != dictionary.getPositionCount(); e.g. projecting a dictionary block onto a dictionary with fewer or more entries.","commonSituations":"Re-encoding a dictionary after filtering or compacting positions without remapping ids; combining dictionary-encoded blocks from different sources whose dictionaries were built independently; operators that rebuild dictionaries with deduplication changing the entry count.","solutions":["Ensure the replacement dictionary has the same position count as the original, remapping ids if entries were removed.","If the dictionaries differ, first call createProjection with an explicit id mapping or rebuild the DictionaryBlock with newIds computed from the new dictionary.","Wrap the call in a check: if (newDictionary.getPositionCount() != block.getDictionary().getPositionCount()) build a new block instead."],"exampleFix":"// before\nBlock projected = dictionaryBlock.createProjection(filteredDictionary);\n// after\nif (filteredDictionary.getPositionCount() != dictionaryBlock.getDictionary().getPositionCount()) {\n    throw new IllegalStateException(\"projection requires same-size dictionary; remap ids instead\");\n}\nBlock projected = dictionaryBlock.createProjection(filteredDictionary);","handlingStrategy":"validation","validationCode":"if (newDictionary.getPositionCount() != dictionaryBlock.getDictionary().getPositionCount()) {\n    throw new IllegalArgumentException(\"cannot project: dictionary sizes differ (\" +\n        newDictionary.getPositionCount() + \" vs \" + dictionaryBlock.getDictionary().getPositionCount() + \")\");\n}","typeGuard":"boolean isProjectable(DictionaryBlock block, Block newDictionary) {\n    return newDictionary.getPositionCount() == block.getDictionary().getPositionCount();\n}","tryCatchPattern":"try {\n    projected = dictionaryBlock.createProjection(newDictionary);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"same position count\")) {\n        projected = rebuildDictionaryBlock(dictionaryBlock, newDictionary); // remap ids\n    } else { throw e; }\n}","preventionTips":["Always derive the new dictionary from the same position set as the original.","Assert dictionary position-count equality in unit tests for dictionary-transforming operators.","Prefer remapping ids over reusing them when compaction changes the dictionary."],"tags":["presto","block","dictionary-encoding","illegal-argument"],"backgroundTag":"dictionary-position-count-mismatch","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"}