elastic/elasticsearch · critical · IllegalStateException

An internal error occurred attempting to define the factory

Error message

An internal error occurred attempting to define the factory class [{}].

What it means

PainlessScriptEngine throws this IllegalStateException when the dynamically generated script factory class cannot be instantiated via reflection. After the compiler writes the factory bytecode and defines it through the loader, it calls factory.getConstructor().newInstance(); any failure (NoSuchMethodException, SecurityException, IllegalAccessException, InstantiationException, InvocationTargetException) is wrapped in this generic error. This is an internal compiler/infrastructure failure, not a user script error.

Source

Thrown at modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngine.java:357

        GeneratorAdapter deterAdapter = new GeneratorAdapter(
            Opcodes.ASM5,
            isResultDeterministic,
            writer.visitMethod(Opcodes.ACC_PUBLIC, methodName, isResultDeterministic.getDescriptor(), null, null)
        );
        deterAdapter.visitCode();
        deterAdapter.push(scriptScope.isDeterministic());
        deterAdapter.returnValue();
        deterAdapter.endMethod();

        writer.visitEnd();
        Class<?> factory = loader.defineFactory(className.replace('/', '.'), writer.toByteArray());

        try {
            return context.factoryClazz.cast(factory.getConstructor().newInstance());
        } catch (Exception exception) {
            // Catch everything to let the user know this is something caused internally.
            throw new IllegalStateException(
                "An internal error occurred attempting to define the factory class [" + className + "].",
                exception
            );
        }
    }

    private static void writeNeedsMethods(Class<?> clazz, ClassWriter writer, Set<String> extractedVariables) {
        for (Method method : clazz.getMethods()) {
            if (method.getName().startsWith("needs")
                && method.getReturnType().equals(boolean.class)
                && method.getParameterTypes().length == 0) {
                String name = method.getName();
                name = name.substring(5);
                name = Character.toLowerCase(name.charAt(0)) + name.substring(1);

                org.objectweb.asm.commons.Method needs = new org.objectweb.asm.commons.Method(
                    method.getName(),
                    MethodType.methodType(boolean.class).toMethodDescriptorString()

View on GitHub (pinned to db6a809a66)

Solutions

  1. Check the caused-by exception (the 'exception' argument) for the root cause — it names the actual reflective failure.
  2. If caused by SecurityManager/permissions, ensure the Elasticsearch security policy permits reflective access to generated script classes.
  3. If no obvious cause, report a Painless bug with the script source, ES version, and JDK version; this is not expected under normal operation.
Defensive patterns

Strategy: try-catch

Try / catch

// This is an internal error; inspect the caused-by exception:
// try { scriptEngine.compile(...); } catch (IllegalStateException e) { log.error('factory init failed', e.getCause()); }

Prevention

When it happens

Trigger: The factory class was generated but its no-arg constructor is missing, inaccessible, or threw during execution. This typically indicates a Painless compiler bug, a classloader/SecurityManager restriction, an ASM version mismatch, or bytecode generation corruption.

Common situations: Running a Painless build with incompatible ASM or JDK versions. Custom security managers blocking reflective instantiation. Bugs in the Painless compiler that emit malformed factory bytecode. Rare edge cases in script compilation.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/a8cc2e1eee7035dc. Report an issue: GitHub.