{"record":{"id":"df756a0174fc5826","repo":"elastic/elasticsearch","slug":"cannot-apply-operation-to-type-boolean-df756a","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":310,"sourceCode":"\n    private static int rem(int a, int b) {\n        return a % b;\n    }\n\n    private static long rem(long a, long b) {\n        return a % b;\n    }\n\n    private static float rem(float a, float b) {\n        return a % b;\n    }\n\n    private static double rem(double a, double b) {\n        return a % b;\n    }\n\n    private static boolean rem(boolean a, boolean b) {\n        throw new ClassCastException(\"Cannot apply [%] operation to type [boolean]\");\n    }\n\n    private static Object rem(Object left, Object right) {\n        if (left instanceof Number) {\n            if (right instanceof Number) {\n                if (left instanceof Double || right instanceof Double) {\n                    return ((Number) left).doubleValue() % ((Number) right).doubleValue();\n                } else if (left instanceof Float || right instanceof Float) {\n                    return ((Number) left).floatValue() % ((Number) right).floatValue();\n                } else if (left instanceof Long || right instanceof Long) {\n                    return ((Number) left).longValue() % ((Number) right).longValue();\n                } else {\n                    return ((Number) left).intValue() % ((Number) right).intValue();\n                }\n            } else if (right instanceof Character) {\n                if (left instanceof Double) {\n                    return ((Number) left).doubleValue() % (char) right;\n                } else if (left instanceof Long) {","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/lang-painless/src/main/java/org/elasticsearch/painless/DefMath.java#L292-L328","documentation":"The remainder operator (%) is defined for all numeric types but not for boolean. DefMath's boolean overload for rem() throws a ClassCastException when one or both def operands resolve to Boolean.","triggerScenarios":"A Painless script applies the % operator to def variables where at least one resolves to Boolean. Example: `def x = true; def y = 3; def z = x % y;`","commonSituations":"A boolean field value is mistakenly used in a modulo expression. Mixing def-typed logical and numeric values in the same arithmetic expression.","solutions":["Ensure both operands are numeric before applying %.","Use an explicit integer type declaration instead of def.","Guard with instanceof and branch to handle non-numeric cases."],"exampleFix":"// before\ndef x = doc['flag'].value;\ndef m = doc['modulus'].value;\ndef z = x % m;\n\n// after\ndef x = doc['flag'].value;\ndef m = doc['modulus'].value;\nif (x instanceof Number && m instanceof Number) {\n    def z = (int) x % (int) m;\n}","handlingStrategy":"type-guard","validationCode":"// Painless: verify both operands are numeric before modulo\ndef a = doc['val1'].value;\ndef b = doc['val2'].value;\nif (a instanceof Number && b instanceof Number) {\n    def result = (int) a % (int) b;\n}","typeGuard":"// Painless type guard for numeric operands\ndef bothNumeric(def a, def b) {\n    return a instanceof Number && b instanceof Number;\n}","tryCatchPattern":null,"preventionTips":["Declare modulo operands as int or long instead of def.","Guard the % operator with instanceof checks on both operands.","Verify field mappings are numeric for values used in modulo expressions."],"tags":["painless","def-type","modulo","boolean","type-mismatch","arithmetic"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:17:08.281Z"}