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

  1. 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.
  2. If the annotation was added/changed, regenerate the javadoc jar (./gradlew javadocJar --rerun-tasks) so HTML and annotations agree.
  3. 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.
  4. If a violation is intentional and justified, suppress it with @SuppressKafkaInternalApiUsage(reason = "...") per KIP-1265.
  5. 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 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


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/28d7d8bce87fab85.json. Report an issue: GitHub.