{"record":{"id":"4998ca7b5566b4a4","repo":"elastic/elasticsearch","slug":"cannot-apply-not-to-type-boolean","errorCode":null,"errorMessage":"Cannot apply not [~] to type [boolean]","messagePattern":"Cannot apply not \\[~\\] to type \\[boolean\\]","errorType":"exception","errorClass":"ClassCastException","httpStatus":null,"severity":"error","filePath":"modules/lang-painless/src/main/java/org/elasticsearch/painless/DefMath.java","lineNumber":52,"sourceCode":"\n    private static int not(int v) {\n        return ~v;\n    }\n\n    private static long not(long v) {\n        return ~v;\n    }\n\n    private static float not(float v) {\n        throw new ClassCastException(\"Cannot apply not [~] to type [float]\");\n    }\n\n    private static double not(double v) {\n        throw new ClassCastException(\"Cannot apply not [~] to type [double]\");\n    }\n\n    private static boolean not(boolean v) {\n        throw new ClassCastException(\"Cannot apply not [~] to type [boolean]\");\n    }\n\n    private static Object not(Object unary) {\n        if (unary instanceof Long) {\n            return ~(Long) unary;\n        } else if (unary instanceof Integer) {\n            return ~(Integer) unary;\n        } else if (unary instanceof Short) {\n            return ~(Short) unary;\n        } else if (unary instanceof Character) {\n            return ~(Character) unary;\n        } else if (unary instanceof Byte) {\n            return ~(Byte) unary;\n        }\n\n        throw new ClassCastException(\"Cannot apply [~] operation to type \" + \"[\" + unary.getClass().getCanonicalName() + \"].\");\n    }\n","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/lang-painless/src/main/java/org/elasticsearch/painless/DefMath.java#L34-L70","documentation":"The bitwise NOT operator (~) operates on individual bits and has no meaning for boolean values. DefMath's boolean overload for not() throws a ClassCastException when a def variable resolves to Boolean at runtime and ~ is applied.","triggerScenarios":"A Painless script applies ~ to a def variable whose runtime value is a Boolean. Example: `def x = true; def y = ~x;`","commonSituations":"A script receives a boolean field value from a document (e.g., a flag) and mistakenly applies a bitwise operator instead of a logical operator (!).","solutions":["Use the logical NOT operator (!) instead of bitwise NOT (~) for boolean values.","If an integer representation is needed, cast to int first: `def y = ~(int) x;`","Use an explicit boolean type declaration so the compiler rejects ~ at compile time."],"exampleFix":"// before\ndef flag = doc['active'].value;\ndef inverted = ~flag;\n\n// after\nboolean flag = doc['active'].value;\nboolean inverted = !flag;","handlingStrategy":"type-guard","validationCode":"// Painless: use logical NOT (!) for boolean, not bitwise NOT (~)\ndef x = doc['flag'].value;\nif (x instanceof Boolean) {\n    boolean inverted = !x;\n} else if (x instanceof Integer || x instanceof Long) {\n    def y = ~x;\n}","typeGuard":"// Painless type guard distinguishing boolean from integral\ndef isIntegral(def value) {\n    return value instanceof Integer || value instanceof Long || value instanceof Short || value instanceof Byte || value instanceof Character;\n}","tryCatchPattern":null,"preventionTips":["Use ! (logical NOT) for boolean values and ~ (bitwise NOT) only for integer types.","Declare boolean fields as `boolean` not `def` so the compiler catches operator misuse.","Review operator choice when working with flag fields from documents."],"tags":["painless","def-type","bitwise","boolean","type-mismatch"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}