apache/kafka · error · MojoFailureException
Found %d internal API usage violations. See report: %s
Error message
Found %d internal API usage violations. See report: %s
What it means
Thrown by the kafka-internal-api-checker Maven plugin (MojoFailureException) when bytecode scanning of the project's compiled classes finds references to Kafka internal (non-public) APIs and the <failOnViolation> flag is true. It enforces KIP-1265 / the @SuppressKafkaInternalApiUsage discipline so consumers of kafka-clients do not silently bind to unstable internals. The message reports the violation count and points to the text report written to <reportFile>.
Source
Thrown at api-checker/maven-plugin/src/main/java/org/apache/kafka/maven/KafkaInternalApiCheckerMojo.java:172
reporter.writeTextReport(violations, suppressions, reportFile);
reporter.printToConsole(violations, suppressions);
getLog().info("Internal API usage check completed. Report written to: " + reportFile.getAbsolutePath());
long unjustified = suppressions.stream().filter(PublicApiViolation::lacksReason).count();
if (unjustified > 0) {
getLog().warn(unjustified + " suppression(s) carry no reason — KIP-1265 requires a justification on every @SuppressKafkaInternalApiUsage");
}
if (violations.isEmpty()) {
getLog().info("No internal API usage found.");
return;
}
String message = String.format("Found %d internal API usage violations. See report: %s",
violations.size(), reportFile.getAbsolutePath());
if (failOnViolation) {
throw new MojoFailureException(message);
}
getLog().warn(message);
}
/**
* Default to the project's main compiled output, matching the Gradle plugin's behaviour
* (which feeds {@code sourceSets.main.output.classesDirs}). Test code legitimately uses
* internal/test utilities, so including it by default would create noise that isn't a
* real consumer-side concern. Users who want to scan test code can opt in by setting
* {@code <classesDirectories>} explicitly.
*/
private List<File> getDefaultClassesDirectories() {
List<File> dirs = new ArrayList<>();
File mainClasses = new File(project.getBuild().getOutputDirectory());
if (mainClasses.exists()) {
dirs.add(mainClasses);
}
return dirs;View on GitHub (pinned to c31c9215e1)
Solutions
- Open the report at the path printed in the message and read each PublicApiViolation entry to see which internal symbol is referenced and from which class.
- Refactor the offending call site to use the supported public API equivalent (e.g. AdminClient / KafkaClient APIs listed in build.gradle javadoc includes).
- If the usage is intentional and justified, annotate with @SuppressKafkaInternalApiUsage(reason=...) per KIP-1265 so it is recorded as a suppression rather than a violation.
- Temporarily set <failOnViolation>false</failOnViolation> in the plugin configuration to unblock CI while the fix is prepared (not recommended as a permanent state).
Example fix
// before org.apache.kafka.common.protocol.ApiKeys apikey = org.apache.kafka.common.protocol.ApiKeys.METADATA; // after (use public API or suppress) @SuppressKafkaInternalApiUsage(reason = "Need APIKeys ordinal for wire compat shim, tracked in KAFKA-12345") org.apache.kafka.common.protocol.ApiKeys apikey = org.apache.kafka.common.protocol.ApiKeys.METADATA;
Defensive patterns
Strategy: validation
Validate before calling
// This is a Maven-plugin build failure (MojoFailureException), not a runtime
// exception. Gate the build *before* enabling failOnViolation:
// 1. Configure <failOnViolation>false</failOnViolation> in pom.xml.
// 2. Read the report at ${project.build.directory}/reports/kafka-internal-api-usage.txt.
// 3. For each VIOLATION line, replace the internal-API call with a public API
// equivalent, or annotate the call site:
// @SuppressKafkaInternalApiUsage(reason="<why public API cannot be used>")
// 4. Re-enable <failOnViolation>true</failOnViolation> only when violations == 0.
//
// CI gate (Groovy/shell) before promoting the build:
// report="${project.build.directory}/reports/kafka-internal-api-usage.txt"
// n=$(grep -c '^VIOLATION' "$report" || true)
// [ "$n" -eq 0 ] || { echo "Fix $n internal-API violations first"; exit 1; } Prevention
- Program only against the public packages (org.apache.kafka.clients.producer|consumer|admin and org.apache.kafka.common.serialization|config|errors); treat anything under *.internal.* or *.internals.* as off-limits.
- Run the kafka-internal-api-checker Mojo in CI on every pull request and gate merge on zero unjustified violations.
- When a suppression is genuinely unavoidable, always give @SuppressKafkaInternalApiUsage a concrete reason — KIP-1265 flags a missing reason as a warning in its own right.
- Pin the Kafka client version; internal APIs can shift between minor releases, so a silent dependency bump can newly flag previously-clean code.
When it happens
Trigger: Binding the kafka-internal-api-checker:maven-plugin goal to the build and having compiled classes that reference org.apache.kafka.* packages outside the public API include list. Triggered during the verify/package phase once classes are compiled. Only fails when failOnViolation=true (the message degrades to a warn otherwise).
Common situations: Upgrading the kafka-clients dependency to a version whose internal classes were refactored/removed, after a transitive dependency starts reaching into internals, or when a previously-public class was reclassified as internal. CI builds that newly enable the plugin will surface long-standing violations for the first time.
Related errors
- No org.apache.kafka:* dependencies found on the project clas
- Failed to check internal API usage: {errorMessage}
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/19a467ef91a3c8da.json.
Report an issue: GitHub.