elastic/elasticsearch · error · IllegalStateException
no execute method found
Error message
no execute method found
What it means
After iterating all non-default methods of the context interface, ScriptClassInfo asserts that an execute method was found. If none is present, this IllegalStateException is thrown. Every Painless-implementable interface must declare a single non-default method literally named execute.
Source
Thrown at modules/lang-painless/src/main/java/org/elasticsearch/painless/ScriptClassInfo.java:99
+ "type ["
+ componentType.getName()
+ "]. Painless can only support getters with return types that are "
+ "whitelisted."
)
);
getMethods.add(
new org.objectweb.asm.commons.Method(
m.getName(),
MethodType.methodType(m.getReturnType()).toMethodDescriptorString()
)
);
}
}
if (executeMethod == null) {
throw new IllegalStateException("no execute method found");
}
ArrayList<FunctionTable.LocalFunction> converters = new ArrayList<>();
FunctionTable.LocalFunction defConverter = null;
for (java.lang.reflect.Method m : baseClass.getMethods()) {
if (m.getName().startsWith("convertFrom")
&& m.getParameterTypes().length == 1
&& m.getReturnType() == returnType
&& Modifier.isStatic(m.getModifiers())) {
if (m.getName().equals("convertFromDef")) {
if (m.getParameterTypes()[0] != Object.class) {
throw new IllegalStateException(
"convertFromDef must take a single Object as an argument, " + "not [" + m.getParameterTypes()[0] + "]"
);
}
defConverter = new FunctionTable.LocalFunction(
m.getName(),
m.getReturnType(),View on GitHub (pinned to db6a809a66)
Solutions
- Add a non-default method named 'execute' to the interface returning a whitelisted type.
- If the method exists but is marked default, remove the default keyword so it becomes abstract.
- Confirm the interface is the one actually passed as baseClass to ScriptClassInfo.
Example fix
// before
public interface MyScript {
default double execute() { return 0; } // skipped -> 1342
}
// after
public interface MyScript {
double execute();
} Defensive patterns
Strategy: validation
Validate before calling
void assertHasExecute(Class<?> iface) {
boolean has = java.util.Arrays.stream(iface.getMethods())
.anyMatch(m -> !m.isDefault() && m.getName().equals("execute"));
if (!has) throw new IllegalStateException("interface needs a non-default execute method");
} Try / catch
try {
new ScriptClassInfo(lookup, MyScript.class);
} catch (IllegalStateException e) {
if (e.getMessage().equals("no execute method found")) {
fail("Add a non-default 'execute' method to " + MyScript.class.getName());
}
throw e;
} Prevention
- Always name the entry method 'execute' (not run/apply).
- Do not mark execute as default.
- Add a compile-time-style reflection test in your context's unit tests.
When it happens
Trigger: Registering a custom ScriptContext whose interface has no method named execute (e.g. it was named run, apply, or compute), or whose only execute is a default method (default methods are skipped by the loop at line 55-56).
Common situations: Renaming execute to a different method name during a refactor; implementing a functional interface from another framework verbatim; making execute a default method by accident.
Related errors
- Painless can only implement interfaces that have a single me
- convertFromDef must take a single Object as an argument, not
- [{}#ARGUMENTS] has length [2] but [{}#execute] takes [1] arg
- Painless needs a constant [String[] PARAMETERS] on all inter
- Error trying to read [{}#ARGUMENTS]
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/28e5a2833502db0f.
Report an issue: GitHub.