{"record":{"id":"1df489ffa5961b03","repo":"elastic/elasticsearch","slug":"cannot-apply-operation-to-types-and-1df489","errorCode":null,"errorMessage":"Cannot apply [<] operation to types [{}] and [{}].","messagePattern":"Cannot apply \\[<\\] operation to types \\[(.+?)\\] and \\[(.+?)\\]\\.","errorType":"exception","errorClass":"ClassCastException","httpStatus":null,"severity":"error","filePath":"modules/lang-painless/src/main/java/org/elasticsearch/painless/DefMath.java","lineNumber":650,"sourceCode":"                }\n            }\n        } else if (left instanceof Character) {\n            if (right instanceof Number) {\n                if (right instanceof Double) {\n                    return (char) left < ((Number) right).doubleValue();\n                } else if (right instanceof Long) {\n                    return (char) left < ((Number) right).longValue();\n                } else if (right instanceof Float) {\n                    return (char) left < ((Number) right).floatValue();\n                } else {\n                    return (char) left < ((Number) right).intValue();\n                }\n            } else if (right instanceof Character) {\n                return (char) left < (char) right;\n            }\n        }\n\n        throw new ClassCastException(\n            \"Cannot apply [<] operation to types \"\n                + \"[\"\n                + left.getClass().getCanonicalName()\n                + \"] and [\"\n                + right.getClass().getCanonicalName()\n                + \"].\"\n        );\n    }\n\n    private static boolean lte(int a, int b) {\n        return a <= b;\n    }\n\n    private static boolean lte(long a, long b) {\n        return a <= b;\n    }\n\n    private static boolean lte(float a, float b) {","sourceCodeStart":632,"sourceCodeEnd":668,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/lang-painless/src/main/java/org/elasticsearch/painless/DefMath.java#L632-L668","documentation":"Thrown by DefMath.lt(Object, Object) when the runtime types of both operands do not match any supported less-than combination. The Object overload checks instanceof Number and instanceof Character; if neither branch matches the actual runtime types, it falls through to this ClassCastException. Only occurs with def-typed operands.","triggerScenarios":"A Painless script applies < to two def-typed values where at least one evaluates at runtime to a non-numeric, non-character type. The compiler emits a call to lt(Object, Object); runtime instanceof dispatch finds no matching branch.","commonSituations":"Comparing a keyword/string field value against a number in a script; def variable holding a List or Map compared with <; field that changed type after a reindex or mapping conflict; script processing heterogeneous documents where the same field name has different types.","solutions":["Declare both operands with explicit types so the compiler catches incompatibility at parse time","Guard with instanceof before comparing: if (a instanceof Number && b instanceof Number) { return ((Number)a).doubleValue() < ((Number)b).doubleValue(); }","Ensure the index mapping types the field consistently as numeric across all documents and indices","If comparing strings, use String.compareTo() or String.compareToIgnoreCase() instead of the < operator"],"exampleFix":"// before\ndef threshold = params['min'];\ndef value = doc['score'].value;\ndef passes = value < threshold;\n\n// after\ndouble value = doc['score'].value;\ndouble threshold = (double) params['min'];\nboolean passes = value < threshold;","handlingStrategy":"type-guard","validationCode":"// Before comparing def values, verify types are compatible\ndef a = doc['field1'].value;\ndef b = params['threshold'];\nif (a instanceof Number && b instanceof Number) {\n  return ((Number) a).doubleValue() < ((Number) b).doubleValue();\n} else if (a instanceof String && b instanceof String) {\n  return ((String) a).compareTo((String) b) < 0;\n} else {\n  return false;\n}","typeGuard":"// Type guard for def relational comparison\nboolean canCompareNumerically(def a, def b) {\n  return a instanceof Number && b instanceof Number;\n}","tryCatchPattern":null,"preventionTips":["Use explicit numeric types instead of def for values involved in comparisons","Validate field types in the mapping before writing comparison scripts","Handle the case where a field is missing: check doc['field'].size() > 0 first","For string comparisons, use String.compareTo() instead of relational operators"],"tags":["painless","elasticsearch","def","type-error","comparison","runtime","less-than"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}