Tencent/APIJSON · error · ClassNotFoundException
找不到脚本语言 " + lang + " 对应的执行引擎!请先依赖相关库并在后端 APIJSONFunctionPars
Error message
找不到脚本语言 " + lang + " 对应的执行引擎!请先依赖相关库并在后端 APIJSONFunctionParser<T, M, L> 中注册!
What it means
The Function row declares a script language, script functions are enabled, but no ScriptExecutor for that language was registered in SCRIPT_EXECUTOR_MAP. APIJSON throws ClassNotFoundException telling you to add the language's library dependency and register its executor in the backend's APIJSONFunctionParser subclass.
Source
Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java:424
}
FunctionBean fb = parseFunction(function, current, false, containRaw);
Map<String, Object> row = FUNCTION_MAP.get(fb.getMethod()); //FIXME fb.getSchema() + "." + fb.getMethod()
if (row == null) {
throw new UnsupportedOperationException("不允许调用远程函数 " + fb.getMethod() + " !");
}
String language = (String) row.get("language");
String lang = "java".equalsIgnoreCase(language) ? null : language;
if (ENABLE_SCRIPT_FUNCTION == false && lang != null) {
throw new UnsupportedOperationException("language = " + language + " 不合法!AbstractFunctionParser.ENABLE_SCRIPT_FUNCTION" +
" == false 时不支持远程函数中的脚本形式!如需支持则设置 AbstractFunctionParser.ENABLE_SCRIPT_FUNCTION = true !");
}
if (lang != null && SCRIPT_EXECUTOR_MAP.get(lang) == null) {
throw new ClassNotFoundException("找不到脚本语言 " + lang + " 对应的执行引擎!请先依赖相关库并在后端 APIJSONFunctionParser<T, M, L> 中注册!");
}
int version = row.get("version") != null ? Integer.parseInt(row.get("version").toString()) : 0;
if (parser.getVersion() < version) {
throw new UnsupportedOperationException("不允许 version = " + parser.getVersion() + " 的请求调用远程函数 " + fb.getMethod() + " ! 必须满足 version >= " + version + " !");
}
String tag = (String) row.get("tag"); // TODO 改为 tags,类似 methods 支持多个 tag。或者干脆不要?因为目前非开放请求全都只能后端指定
if (tag != null && tag.equals(parser.getTag()) == false) {
throw new UnsupportedOperationException("不允许 tag = " + parser.getTag() + " 的请求调用远程函数 " + fb.getMethod() + " ! 必须满足 tag = " + tag + " !");
}
String[] methods = StringUtil.split((String) row.get("methods"));
List<String> ml = methods == null || methods.length <= 0 ? null : Arrays.asList(methods);
if (ml != null && ml.contains(parser.getMethod().toString()) == false) {
throw new UnsupportedOperationException("不允许 method = " + parser.getMethod() + " 的请求调用远程函数 " + fb.getMethod() + " ! 必须满足 method 在 " + Arrays.toString(methods) + "内 !");
}
try {
return invoke(parser, fb.getMethod(), fb.getTypes(), fb.getValues(), (String) row.get("returnType"), current, SCRIPT_EXECUTOR_MAP.get(lang));View on GitHub (pinned to 5284052872)
Solutions
- Add the script engine dependency (e.g. org.graalvm.js:js) to the backend build.
- Register an executor at startup: AbstractFunctionParser.putScriptExecutor("javascript", new JavaScriptExecutor()).
- Or change the Function row's language to 'java' and implement it as a Java remote function.
- Verify the language string matches exactly (case) what you registered.
Example fix
// before: language='javascript' row, no executor
// after
static {
AbstractFunctionParser.putScriptExecutor("javascript", new JavaScriptExecutor());
} Defensive patterns
Strategy: validation
Validate before calling
String lang = (String) functionRow.get("language");
if (lang != null && !"java".equalsIgnoreCase(lang)
&& AbstractFunctionParser.SCRIPT_EXECUTOR_MAP.get("java".equalsIgnoreCase(lang) ? null : lang) == null) {
// missing executor: register one or change the row language
} Try / catch
try { parser.invoke(fn, current); } catch (ClassNotFoundException e) { if (e.getMessage().contains("执行引擎")) { /* register ScriptExecutor + dependency */ } throw e; } Prevention
- Register all script executors in the same startup init block, keyed exactly to the language strings used in Function rows.
- Pin script engine dependencies in the build file and verify them in a startup self-test.
- Keep a checklist mapping language string -> dependency -> executor class.
When it happens
Trigger: Function row language='python' (for example) and no putScriptExecutor('python', ...) call exists; or the executor registration code lives in a demo class that was not ported to the real backend.
Common situations: Migrating from the APIJSON demo project but omitting the executor registration init; upgrading removed an optional script-engine dependency (e.g. GraalJS) from the classpath.
Related errors
- 不允许调用远程函数 " + fb.getMethod() + " !
- language = " + language + " 不合法!AbstractFunctionParser.ENABL
- 远程函数 " + methodName + " 的实际返回值类型 " + (rt == null ? null : rt
- 远程函数 " + methodName + " 在 Function 表中的配置的类型 " + returnType +
- 远程函数 " + methodName + " 的实际返回值类型 " + (rt == null ? null : rt
AI-assisted analysis of Tencent/APIJSON@5284052872 (2026-08-14).
Data as JSON: /api/errors/335ac4440dc775e5.
Report an issue: GitHub.