{"record":{"id":"dcfa332612a216f9","repo":"elastic/elasticsearch","slug":"cannot-cast-to","errorCode":null,"errorMessage":"Cannot cast {} to {}","messagePattern":"Cannot cast (.+?) to (.+?)","errorType":"exception","errorClass":"ClassCastException","httpStatus":null,"severity":"error","filePath":"modules/lang-painless/src/main/java/org/elasticsearch/painless/DefMath.java","lineNumber":1286,"sourceCode":"        // bind to the boxed type\n        MethodHandle cast = DYNAMIC_CAST.bindTo(desired);\n        return MethodHandles.filterReturnValue(target, cast);\n    }\n\n    /** Forces a cast to class A for target (only if types differ) */\n    public static MethodHandle cast(Class<?> classA, MethodHandle target) {\n        MethodType newType = MethodType.methodType(classA).unwrap();\n        MethodType targetType = MethodType.methodType(target.type().returnType()).unwrap();\n\n        // don't do a conversion if types are the same. explicitCastArguments has this opto,\n        // but we do it explicitly, to make the boolean check simpler\n        if (newType.returnType() == targetType.returnType()) {\n            return target;\n        }\n\n        // we don't allow the to/from boolean conversions of explicitCastArguments\n        if (newType.returnType() == boolean.class || targetType.returnType() == boolean.class) {\n            throw new ClassCastException(\"Cannot cast \" + targetType.returnType() + \" to \" + newType.returnType());\n        }\n\n        // null return values are not possible for our arguments.\n        return MethodHandles.explicitCastArguments(target, target.type().changeReturnType(newType.returnType()));\n    }\n}\n","sourceCodeStart":1268,"sourceCodeEnd":1293,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/lang-painless/src/main/java/org/elasticsearch/painless/DefMath.java#L1268-L1293","documentation":"DefMath.cast throws this ClassCastException at compile/link time when an explicit cast in a Painless script involves a boolean on either side. Java's explicitCastArguments would silently allow boolean<->numeric conversions in some JVM paths, but Painless deliberately forbids them: casts to or from boolean are rejected with this error. All other primitive-to-primitive casts go through explicitCastArguments normally.","triggerScenarios":"Writing an explicit cast in Painless that involves boolean: 'boolean b = (boolean) 1;' or 'int i = (int) true;'. The compiler's AnalyzerCaster resolves to DefMath.cast, which detects a boolean on either the source or target side and throws.","commonSituations":"Scripts ported from C/C++/JavaScript where truthiness casts (int->bool, bool->int) are idiomatic. Misunderstanding of Painless's stricter cast rules versus Java autoboxing. Attempts to coerce numeric flags into booleans for conditional logic.","solutions":["Replace numeric-to-boolean casts with an explicit comparison: 'boolean b = (x != 0);'.","Replace boolean-to-numeric casts with a ternary: 'int i = b ? 1 : 0;'.","Avoid the cast entirely by restructuring the conditional logic to use the boolean directly."],"exampleFix":"// before\nint flag = 1;\nboolean active = (boolean) flag;  // throws\n// after\nint flag = 1;\nboolean active = (flag != 0);","handlingStrategy":"validation","validationCode":"// Never cast to/from boolean. Use explicit comparisons instead:\n// int flag = 1;\n// boolean active = (flag != 0);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never write (boolean) or (int)/(long) casts involving boolean.","Use comparison operators (!= 0) for numeric-to-boolean.","Use ternary (b ? 1 : 0) for boolean-to-numeric."],"tags":["painless","elasticsearch","type-error","casting","boolean","compile-time"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}