{"record":{"id":"e7baf273d6d5b8db","repo":"elastic/elasticsearch","slug":"cannot-apply-operation-to-type-boolean-e7baf2","errorCode":null,"errorMessage":"Cannot apply [<<] operation to type [boolean]","messagePattern":"Cannot apply \\[<<\\] operation to type \\[boolean\\]","errorType":"exception","errorClass":"ClassCastException","httpStatus":null,"severity":"error","filePath":"modules/lang-painless/src/main/java/org/elasticsearch/painless/DefMath.java","lineNumber":1004,"sourceCode":"\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\n    private static long rsh(long a, long b) {\n        return a >> b;\n    }\n","sourceCodeStart":986,"sourceCodeEnd":1022,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/lang-painless/src/main/java/org/elasticsearch/painless/DefMath.java#L986-L1022","documentation":"Thrown by DefMath.lsh(boolean, long) which unconditionally throws. When the left operand is statically typed boolean, the compiler's promote() method yields boolean.class for the left side, selecting the lsh(boolean, long) overload. Left-shift has no semantics for boolean values; the overload exists for method-table completeness but always raises this exception.","triggerScenarios":"A Painless script applies the << operator where the left operand is statically typed as boolean. The shift amount (right operand) is promoted to long. The compiler selects lsh(boolean, long) which unconditionally throws.","commonSituations":"Bit-shift on a boolean-typed field; boolean variable mistakenly used in a shift expression; refactoring code that previously used integer flags but was changed to boolean fields; boolean-typed runtime field in encoding/packing logic.","solutions":["Convert the boolean to an integer before shifting: int iv = b ? 1 : 0; int result = iv << shift;","Change the field mapping to an integer type (0/1) if bit-shifting is the intended use case","Re-examine the logic: shifting a boolean is almost certainly a design error"],"exampleFix":"// before\nboolean flag = doc['enabled'].value;\nint packed = flag << 3;\n\n// after\nint flag = doc['enabled'].value ? 1 : 0;\nint packed = flag << 3;","handlingStrategy":"type-guard","validationCode":"// Before left-shift on boolean, convert to int\nboolean flag = doc['enabled'].value;\nint iv = flag ? 1 : 0;\nreturn iv << 3;","typeGuard":"// Check that the left operand is not boolean 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 boolean-typed variables — convert to int (0/1) first","If bit-shifting is needed, change the field mapping from boolean to integer","Review scripts that were refactored from integer flags to boolean fields","Shifting a boolean is almost certainly a logic error — re-examine the intent"],"tags":["painless","elasticsearch","boolean","type-error","shift","runtime","left-shift"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}