flowable/flowable-engine · error · IllegalStateException

Invalid ScriptEngineFactory:

Error message

Invalid ScriptEngineFactory: 

What it means

Extender.resolveScriptEngine loads the class named in a script engine factory descriptor inside an OSGi bundle and validates that it implements javax.script.ScriptEngineFactory. If the loaded class does not implement that interface, it throws IllegalStateException('Invalid ScriptEngineFactory: <class name>'). This protects the subsequent cast and instantiation from a ClassCastException.

Source

Thrown at modules/flowable-osgi/src/main/java/org/flowable/osgi/Extender.java:381

            if (reg != null) {
                reg.unregister();
            }
        }

        @SuppressWarnings({"rawtypes"})
        @Override
        public ScriptEngine resolveScriptEngine(String name) {
            try {
                String className;
                try (InputStream input = configFile.openStream()) {
                    className = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)).lines()
                            .map(line -> line.split("#", 2)[0].trim())
                            .filter(Predicate.not(String::isBlank))
                            .findFirst().orElse(null);
                }
                Class<?> cls = bundle.loadClass(className);
                if (!ScriptEngineFactory.class.isAssignableFrom(cls)) {
                    throw new IllegalStateException("Invalid ScriptEngineFactory: " + cls.getName());
                }
                ScriptEngineFactory factory = (ScriptEngineFactory) cls.getConstructor().newInstance();
                List<String> names = factory.getNames();
                for (String test : names) {
                    if (test.equals(name)) {
                        ClassLoader old = Thread.currentThread().getContextClassLoader();
                        ScriptEngine engine;
                        try {
                            // JRuby seems to require the correct TCCL to call
                            // getScriptEngine
                            Thread.currentThread().setContextClassLoader(factory.getClass().getClassLoader());
                            engine = factory.getScriptEngine();
                        } finally {
                            Thread.currentThread().setContextClassLoader(old);
                        }
                        LOGGER.trace("Resolved ScriptEngineFactory: {} for expected name: {}", engine, name);
                        return engine;
                    }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Correct the factory class name in the script engine descriptor to a class implementing ScriptEngineFactory
  2. Verify the bundle exporting the script engine factory is deployed and its class is public with a no-arg constructor
  3. Check for version mismatches between the script engine library and the descriptor file
  4. Rebuild/redeploy the bundle if the class was recently renamed

Example fix

// before (descriptor content)
com.example.MyEngineImpl   // does not implement ScriptEngineFactory
// after
com.example.MyEngineFactory // implements javax.script.ScriptEngineFactory
Defensive patterns

Strategy: validation

Validate before calling

Class<?> cls = bundle.loadClass(factoryClassName);
if (!javax.script.ScriptEngineFactory.class.isAssignableFrom(cls)) {
    throw new IllegalArgumentException(factoryClassName + " does not implement ScriptEngineFactory");
}

Try / catch

try {
    ScriptEngine engine = scriptEngine.getEngineByName(language);
} catch (FlowableException e) {
    if (e.getMessage().startsWith("problem resolving scripting engine")) {
        logger.error("Script engine resolution failed for {}: {}", language, e.getCause().getMessage());
    }
    throw e;
}

Prevention

When it happens

Trigger: A bundle's script-engine registration file (e.g. META-INF/services or the OSGi launcher config) lists a className that resolves via bundle.loadClass to a class that is not a ScriptEngineFactory, during resolveScriptEngine (called from resolvedEngine).

Common situations: Typo'd or wrong class name in the engine factory descriptor; a class was renamed/refactored across Flowable or script engine versions; wrong bundle's classloader resolving an unrelated class with the same name.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/0e08cb2ef19320ce. Report an issue: GitHub.