{"record":{"id":"78b30f2915f406b3","repo":"elastic/elasticsearch","slug":"cannot-apply-operation-to-type-double","errorCode":null,"errorMessage":"Cannot apply [<<] operation to type [double]","messagePattern":"Cannot apply \\[<<\\] operation to type \\[double\\]","errorType":"exception","errorClass":"ClassCastException","httpStatus":null,"severity":"error","filePath":"modules/lang-painless/src/main/java/org/elasticsearch/painless/DefMath.java","lineNumber":1000,"sourceCode":"    }\n\n    // shift operators, valid for any integral types, but does not promote.\n    // we implement all shifts as long shifts, because the extra bits are ignored anyway.\n\n    private static int lsh(int a, long b) {\n        return a << b;\n    }\n\n    private static long lsh(long a, long b) {\n        return a << b;\n    }\n\n    private static float lsh(float a, long b) {\n        throw new ClassCastException(\"Cannot apply [<<] operation to type [float]\");\n    }\n\n    private static double lsh(double a, long b) {\n        throw new ClassCastException(\"Cannot apply [<<] operation to type [double]\");\n    }\n\n    private static boolean lsh(boolean a, long b) {\n        throw new ClassCastException(\"Cannot apply [<<] operation to type [boolean]\");\n    }\n\n    public static Object lsh(Object left, long right) {\n        if (left instanceof Long) {\n            return (long) (left) << right;\n        } else {\n            return intIntegralValue(left) << right;\n        }\n    }\n\n    private static int rsh(int a, long b) {\n        return a >> b;\n    }\n","sourceCodeStart":982,"sourceCodeEnd":1018,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/lang-painless/src/main/java/org/elasticsearch/painless/DefMath.java#L982-L1018","documentation":"Thrown by DefMath.lsh(double, long) which unconditionally throws. When the left operand is statically typed double, the compiler's promote() method yields double.class for the left side, selecting the lsh(double, long) overload. Left-shift is only defined for integral types; the double overload always fails.","triggerScenarios":"A Painless script applies the << operator where the left operand is statically typed as double. The shift amount (right operand) is promoted to long. The compiler selects lsh(double, long) which unconditionally throws.","commonSituations":"Bit-shift on a double-typed field or scaled_float mapping; double variable used in shift encoding/packing logic; refactoring integer shift code to operate on double fields; double-typed runtime field in bit-manipulation logic.","solutions":["Cast the double left operand to long before shifting: long lv = (long) v; long result = lv << shift;","Change the field mapping to a long integer type if bit-shifting is the intended use case","Use multiplication (v * Math.pow(2, shift)) if the goal is scaling rather than bit manipulation"],"exampleFix":"// before\ndouble val = doc['encoded'].value;\ndouble shifted = val << 4;\n\n// after\nlong val = (long) doc['encoded'].value;\nlong shifted = val << 4;","handlingStrategy":"type-guard","validationCode":"// Before left-shift on double, cast to long\ndouble val = doc['encoded'].value;\nlong lv = (long) val;\nreturn lv << 4;","typeGuard":"// Check that the left operand is integral before shift\nboolean isShiftable(Object v) {\n  return v instanceof Integer || v instanceof Long || \n         v instanceof Short || v instanceof Byte;\n}","tryCatchPattern":null,"preventionTips":["Never apply << to double-typed variables — cast to long first","Change field mapping from double/scaled_float to long if bit-shifting is needed","Consider multiplication (v * Math.pow(2, n)) if scaling rather than bit manipulation is the goal","Audit scripts that use << on fields mapped as double or scaled_float"],"tags":["painless","elasticsearch","double","type-error","shift","runtime","left-shift"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}