{"record":{"id":"2f0e25633aeeda2f","repo":"elastic/elasticsearch","slug":"unsupported-bitsperdim","errorCode":null,"errorMessage":"Unsupported bitsPerDim: {}","messagePattern":"Unsupported bitsPerDim: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"libs/simdvec/src/main/java/org/elasticsearch/simdvec/AsymmetricHashingScorer.java","lineNumber":85,"sourceCode":"\n        byte[] packed = new byte[bitsPerDim * planeBytes];\n        switch (bitsPerDim) {\n            case 1 -> ESVectorUtil.pack1BitValues(rounded, packed);\n            case 2 -> ESVectorUtil.stride2BitValues(rounded, packed);\n            case 4 -> ESVectorUtil.stride4BitValues(rounded, packed);\n            case 3, 8 -> {\n                // TODO: optimized implementations\n                for (int j = 0; j < nDims; j++) {\n                    int byteIdx = j >>> 3;\n                    int bitIdx = 7 - (j & 7); // MSB-first\n                    for (int p = 0; p < bitsPerDim; p++) {\n                        if ((rounded[j] & (1 << p)) != 0) {\n                            packed[p * planeBytes + byteIdx] |= (byte) (1 << bitIdx);\n                        }\n                    }\n                }\n            }\n            default -> throw new IllegalArgumentException(\"Unsupported bitsPerDim: \" + bitsPerDim);\n        }\n\n        return packed;\n    }\n\n    /**\n     * Scores a single database vector from its packed bit-plane representation against a\n     * precomputed transformed query. This is the inner-loop method for posting list scoring.\n     * <p>\n     * The packed format is bitsPerDim bit-planes, each ceil(nDims/8) bytes, MSB-first.\n     * Codes represent centered levels. The unsigned code value is reconstructed from bit planes,\n     * then shifted back to centered by subtracting (numLevels-1)/2.\n     * dot = sum_j queryTransformed[j] * centeredCode[j]\n     *     = sum over planes of (2^p * sum_of_qt_where_bit_p_set) - centerOffset * sumAll\n     *\n     * @param queryTransformed precomputed query @ W (raw projection, not centered)\n     * @param queryDotCentroid precomputed query . centroid for this cluster\n     * @param packedCodes bit-plane packed codes","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/simdvec/src/main/java/org/elasticsearch/simdvec/AsymmetricHashingScorer.java#L67-L103","documentation":"Thrown by AsymmetricHashingScorer.pack (or related packing logic) when bitsPerDim is not one of the supported values. The switch handles 1, 2, 4 (optimized), and 3, 8 (fallback), with a default that rejects everything else (e.g. 5, 6, 7, 9+). IllegalArgumentException — the caller passed a quantization bit-width this scorer cannot encode.","triggerScenarios":"Constructing/using an AsymmetricHashing model with bitsPerDim outside {1,2,3,4,8}; reading a quantization config whose bits_per_dim was set to an unsupported value; a model trained with a bit width the runtime scorer has not implemented.","commonSituations":"User-configured dense_vector quantization with an unusual bit width; model artifacts produced by a newer trainer exposing bit widths the runtime does not yet support; tests sweeping bit widths without gating on the supported set.","solutions":["Use one of the supported bitsPerDim values: 1, 2, 3, 4, or 8.","Validate bitsPerDim at config/model-load time against the supported set and reject early with a clear error before reaching the scorer.","If a new bit width is required, add an optimized (or fallback) case branch and a test before exposing it.","Check the dense_vector / quantization config that produced the model for a typo or unsupported value."],"exampleFix":"// before\nint bitsPerDim = config.bitsPerDim(); // could be 6\nscorer.pack(query, bitsPerDim);\n\n// after\nif (!Set.of(1,2,3,4,8).contains(config.bitsPerDim())) {\n    throw new IllegalArgumentException(\"bits_per_dim must be one of 1,2,3,4,8\");\n}\nscorer.pack(query, config.bitsPerDim());","handlingStrategy":"validation","validationCode":"private static final Set<Integer> SUPPORTED_BITS = Set.of(1, 2, 3, 4, 8);\nif (!SUPPORTED_BITS.contains(bitsPerDim)) {\n    throw new IllegalArgumentException(\"bits_per_dim must be one of 1,2,3,4,8; got \" + bitsPerDim);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Restrict bitsPerDim to {1,2,3,4,8}.","Validate at model/config load, not inside the scoring hot loop.","Add an explicit case branch + test before exposing a new bit width."],"tags":["simdvec","quantization","scoring","vectors"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}