{"record":{"id":"7ce82a200637e93b","repo":"apache/dubbo","slug":"unsupported-route-engine-type-type","errorCode":null,"errorMessage":"unsupported route engine type: {type}","messagePattern":"unsupported route engine type: (.+?)","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptStateRouter.java","lineNumber":129,"sourceCode":"     */\n    private String getRule(URL url) {\n        String vRule = url.getParameterAndDecoded(RULE_KEY);\n        if (StringUtils.isEmpty(vRule)) {\n            throw new IllegalStateException(\"route rule can not be empty.\");\n        }\n        return vRule;\n    }\n\n    /**\n     * create ScriptEngine instance by type from url parameters, then cache it\n     */\n    private ScriptEngine getEngine(URL url) {\n        String type = url.getParameter(TYPE_KEY, DEFAULT_SCRIPT_TYPE_KEY);\n\n        return ConcurrentHashMapUtils.computeIfAbsent(ENGINES, type, t -> {\n            ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName(type);\n            if (scriptEngine == null) {\n                throw new IllegalStateException(\"unsupported route engine type: \" + type);\n            }\n            return scriptEngine;\n        });\n    }\n\n    @Override\n    protected BitList<Invoker<T>> doRoute(\n            BitList<Invoker<T>> invokers,\n            URL url,\n            Invocation invocation,\n            boolean needToPrintMessage,\n            Holder<RouterSnapshotNode<T>> nodeHolder,\n            Holder<String> messageHolder)\n            throws RpcException {\n        if (engine == null || function == null) {\n            if (needToPrintMessage) {\n                messageHolder.set(\"Directly Return. Reason: engine or function is null\");\n            }","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/apache/dubbo/blob/3a3043227f5571d25eb2889de5bca22f2914843b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptStateRouter.java#L111-L147","documentation":"Thrown by ScriptStateRouter.getEngine() when ScriptEngineManager.getEngineByName(type) returns null — no JSR-223 script engine is registered under the configured name. The 'type' parameter defaults to a standard type (DEFAULT_SCRIPT_TYPE_KEY) but if the named engine is not on the classpath the router cannot function.","triggerScenarios":"Configuring a script router with type=<name> for which no javax.script engine is available. Most common: using type=javascript on Java 15+, where Nashorn was removed and getEngineByName('javascript'/'js') returns null.","commonSituations":"Running on Java 15+ (Nashorn removed) and using javascript script routing; specifying an engine name that does not match any registered engine (e.g., 'groovy' without the groovy-jsr223 dependency); missing the JSR-223 implementation jar on the classpath.","solutions":["Add a JSR-223 engine implementation to the classpath: for JavaScript on Java 15+ add the standalone Nashorn (org.openjdk.nashorn:nashorn-core) or GraalJS (org.graalvm.js:js-scriptengine + js); for Groovy add groovy-jsr223.","Use an engine name that the registered engine actually publishes (try 'nashorn', 'js', 'graal.js', or 'groovy' depending on the jar).","If no engine is desired, switch the router to a different type (condition/script-free) or remove it."],"exampleFix":"# before (broken, Java 15+): nashorn removed -> getEngineByName returns null\nscript://0.0.0.0/...?type=javascript&rule=...\n\n# after: add graaljs to pom and use its engine name\n# pom: org.graalvm.js:js-scriptengine, org.graalvm.js:js, org.graalvm.regex\nscript://0.0.0.0/...?type=graal.js&rule=...\n# (or add org.openjdk.nashorn:nashorn-core and keep type=javascript)","handlingStrategy":"validation","validationCode":"// Validate the script engine is available before constructing the router\nString type = url.getParameter(TYPE_KEY, DEFAULT_SCRIPT_TYPE_KEY);\nScriptEngine engine = new ScriptEngineManager().getEngineByName(type);\nif (engine == null) {\n    throw new IllegalArgumentException(\n        \"No JSR-223 script engine named '\" + type + \"' on classpath. \"\n            + \"Add nashorn-core (Java 15+) or graaljs/groovy-jsr223.\");\n}\nreturn new ScriptStateRouter<>(url);","typeGuard":"// Guard: an engine for the requested type exists\nstatic boolean engineAvailable(String type) {\n    return new ScriptEngineManager().getEngineByName(type) != null;\n}","tryCatchPattern":"try {\n    new ScriptStateRouter<>(url);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"unsupported route engine type\")) {\n        // engine jar missing; log and fall back to a non-script router\n        log.error(\"Script router engine missing: \" + e.getMessage()\n            + \" Add org.openjdk.nashorn:nashorn-core or graaljs.\");\n    } else throw e;\n}","preventionTips":["On Java 15+, add a JSR-223 engine jar (nashorn-core or GraalJS) to use javascript routing.","Use an engine name that the registered engine actually publishes.","Smoke-test getEngineByName(type) in your environment before deploying script routing."],"tags":["router","script","jvm","dependency","java-version"],"backgroundTag":null,"analyzedSha":"3a3043227f5571d25eb2889de5bca22f2914843b","analyzedAt":"2026-08-14T00:43:19.853Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}