apache/kafka · error · GradleException
Found %d public API violations. See report: %s
Error message
Found %d public API violations. See report: %s
What it means
Thrown by KafkaPublicApiCheckerTask.checkPublicApi() when checkPublicApiConsistency(jarFile) returned one or more violations and failOnViolation is true (its default). A violation here means a mismatch between the public API surface declared by @InterfaceAudience.Public annotations in the project jars and the published javadoc — e.g. a type annotated @InterfaceAudience.Public is missing from the javadoc jar, or the javadoc documents a type that is not part of the annotated public surface.
Source
Thrown at api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaPublicApiCheckerTask.java:122
// Print summary to console
reporter.printToConsole(violations, suppressions);
getLogger().info("Public API check completed. Report written to: {}", report.getAbsolutePath());
if (!suppressions.isEmpty()) {
getLogger().lifecycle("{} suppression(s) honoured — see report for justifications.", suppressions.size());
long unjustified = suppressions.stream().filter(PublicApiViolation::lacksReason).count();
if (unjustified > 0) {
getLogger().warn("{} suppression(s) carry no reason — KIP-1265 requires a justification on every @SuppressKafkaInternalApiUsage", unjustified);
}
}
if (!violations.isEmpty()) {
String message = String.format("Found %d public API violations. See report: %s",
violations.size(), report.getAbsolutePath());
if (failOnViolation.get()) {
throw new GradleException(message);
} else {
getLogger().warn(message);
}
} else {
getLogger().info("No public API violations found.");
}
} catch (IOException e) {
throw new GradleException("Failed to check public API: " + e.getMessage(), e);
}
}
private File getJavadocJarFile() {
if (!javadocJarPath.isPresent()) {
throw new GradleException("kafkaPublicApiChecker.javadocJarPath is not set. "
+ "Either configure it explicitly on the extension, or apply this plugin to a "
+ "project that defines a 'javadocJar' Jar task whose output the plugin can "
+ "wire automatically.");View on GitHub (pinned to c31c9215e1)
Solutions
- Open the report at the path in the message and read each violation to identify whether the javadoc is stale (page missing) or the annotation is wrong.
- If the annotation was added/changed, regenerate the javadoc jar (./gradlew javadocJar --rerun-tasks) so HTML and annotations agree.
- If the annotation is wrong, correct it: add @InterfaceAudience.Public to a class that should be public, or remove it from one that should not.
- If a violation is intentional and justified, suppress it with @SuppressKafkaInternalApiUsage(reason = "...") per KIP-1265.
- During migration only, set kafkaPublicApiChecker.failOnViolation = false to surface the report without failing while triage happens.
Example fix
// before
@InterfaceAudience.Public
public class NewClient { ... }
// javadocJar was not regenerated -> violation: NewClient missing from javadoc
// after — regenerate the docs so the published surface matches
// ./gradlew clean javadocJar kafkaPublicApiCheck --rerun-tasks Defensive patterns
Strategy: validation
Validate before calling
// Keep javadoc HTML and @InterfaceAudience.Public in sync; run warn-only locally
tasks.named<org.apache.kafka.gradle.KafkaPublicApiCheckerTask>("kafkaPublicApiChecker").configure {
failOnViolation = (System.getenv("CI") != null)
}
// Quick consistency grep: every type documented should carry @InterfaceAudience.Public
// rg -l '@InterfaceAudience.Public' src/main | sort vs. rg -l '<h[12]' build/docs/javadoc Prevention
- When adding a public type, update its javadoc HTML and the @InterfaceAudience.Public annotation together — the checker flags drift between the two.
- Open the report path named in the message; each violation names the symbol and whether it is missing from javadoc or from the annotation set.
- Use @SuppressKafkaInternalApiUsage(reason = "...") for documented exceptions, and keep every suppression justified (the build warns on reason-less ones).
When it happens
Trigger: Line 121-122: result.violations() is non-empty and failOnViolation.get() is true. Produced when a class is annotated @InterfaceAudience.Public but the javadoc jar lacks the corresponding HTML page (or vice versa), or when the @InterfaceAudience annotation was added/removed without regenerating the javadoc.
Common situations: Promoting an internal class to public by adding @InterfaceAudience.Public but forgetting to regenerate javadoc; removing the annotation from a previously-public class whose javadoc page still exists; an upstream javadoc generation that silently skipped a class due to an error; misaligned javadoc jar version vs the source jars used for the annotation scan.
Related errors
- Javadoc JAR file not found: {path}. Make sure the javadoc ta
- kafkaPublicApiChecker.javadocJarPath is not set. Either conf
- No org.apache.kafka:* dependencies found on the configured k
- Failed to check internal API usage: {errorMessage}
- Found %d internal API usage violations. See report: %s
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/28d7d8bce87fab85.json.
Report an issue: GitHub.