elastic/elasticsearch · error · IllegalStateException
Forbidden APIs cli failed: {forbiddenApisOutput}
Error message
Forbidden APIs cli failed: {forbiddenApisOutput} What it means
Thrown by ThirdPartyAuditTask.runForbiddenAPIsCli when the forbiddenapis CLI exits with a code not in EXPECTED_EXIT_CODES. The captured stderr (forbiddenApisOutput) is attached so the developer can see the actual forbiddenapis error output. This is the generic 'forbiddenapis reported violations or crashed' failure path.
Source
Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/ThirdPartyAuditTask.java:424
}
spec.jvmArgs("-Xmx1g");
spec.getMainClass().set("de.thetaphi.forbiddenapis.cli.CliMain");
spec.args("-f", getSignatureFile().getAbsolutePath(), "-d", getJarExpandDir(), "--debug", "--allowmissingclasses");
spec.setErrorOutput(errorOut);
if (getLogger().isInfoEnabled() == false) {
spec.setStandardOutput(new NullOutputStream());
}
spec.setIgnoreExitValue(true);
});
if (OS.current().equals(OS.LINUX) && result.getExitValue() == SIG_KILL_EXIT_VALUE) {
throw new IllegalStateException("Third party audit was killed buy SIGKILL, could be a victim of the Linux OOM killer");
}
final String forbiddenApisOutput;
try (ByteArrayOutputStream outputStream = errorOut) {
forbiddenApisOutput = outputStream.toString(StandardCharsets.UTF_8);
}
if (EXPECTED_EXIT_CODES.contains(result.getExitValue()) == false) {
throw new IllegalStateException("Forbidden APIs cli failed: " + forbiddenApisOutput);
}
return forbiddenApisOutput;
}
/** Returns true iff the build Java version is the same as the given version. */
private boolean isJavaVersion(JavaVersion version) {
if (getRuntimeJavaVersion().isPresent()) {
return getRuntimeJavaVersion().get().equals(version);
}
return version.getMajorVersion().equals(VersionProperties.getBundledJdkMajorVersion());
}
private Set<String> runJdkJarHellCheck() throws IOException {
ByteArrayOutputStream standardOut = new ByteArrayOutputStream();
ExecResult execResult = execOperations.javaexec(spec -> {
spec.classpath(getJdkJarHellClasspath(), getThirdPartyClasspath());
spec.getMainClass().set(JDK_JAR_HELL_MAIN_CLASS);
spec.args(getJarExpandDir());View on GitHub (pinned to db6a809a66)
Solutions
- Read the full forbiddenApisOutput text in the exception/Gradle log to see which classes/APIs were flagged.
- For legitimate violations, fix the calling code or add a justified class-level exclusion in thirdPartyAudit { ... }.
- If forbiddenapis itself errored (e.g. signature mismatch), update or align the signature file / bundled JDK version.
- Re-run :<project>:thirdPartyAudit after the fix to confirm a clean (expected) exit code.
Example fix
// before: code calls a forbidden API Runtime.getRuntime().exit(0); // after: use an allowed alternative System.exit(0); // if permitted by signatures, otherwise remove the call
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check: scan sources for known forbidden patterns is not feasible generically; // instead keep forbiddenapis signatures updated and run the audit frequently in CI.
Try / catch
try { String out = runForbiddenAPIsCli(); }
catch (IllegalStateException e) {
// e.getMessage() contains the full forbiddenapis output — fix code or add justified exclusion
throw e;
} Prevention
- Run thirdPartyAudit in CI on every PR so violations surface at review time.
- Keep the signature file aligned with the bundled JDK version.
- When adding a dependency, run the audit locally to catch newly-introduced forbidden calls.
When it happens
Trigger: After running forbiddenapis with setIgnoreExitValue(true), the exit code is checked against EXPECTED_EXIT_CODES. A non-matching code means forbiddenapis either found forbidden API usages (its normal non-zero exit) or hit an internal error; the captured stderr is surfaced in the exception message.
Common situations: Code uses an API forbidden by the configured signature file (the intended failure mode); signature file references a class/method that no longer exists causing forbiddenapis to error; misconfigured -d jar expand dir; JDK version mismatch between the build and the forbiddenapis signatures; a new dependency introduces forbidden calls.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Third party audit task is not configured correctly
- Unnecessary split package ignores found
- Unsupported classpath element: {}
- Third party audit was killed buy SIGKILL, could be a victim
- Failed to write keywords report
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/7f379179ce382cfe.
Report an issue: GitHub.