apache/kafka · error · GradleException

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 KafkaInternalApiCheckerTask.reportResults() when the bytecode scan found one or more internal Kafka API references in the project's compiled classes and failOnViolation is true (its default). Each violation corresponds to a class in build/classes that references a Kafka type not annotated @InterfaceAudience.Public, i.e. a package-private or internal-API usage that is not safe for external consumers. The report path in the message points to the human-readable breakdown of every violation and honoured suppression.

Source

Thrown at api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaInternalApiCheckerTask.java:148

        reporter.writeTextReport(violations, suppressions, report);
        reporter.printToConsole(violations, suppressions);

        getLogger().info("Internal API usage check completed. Report written to: {}", report.getAbsolutePath());

        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()) {
            getLogger().info("No internal API usage found.");
            return;
        }

        String message = String.format("Found %d internal API usage violations. See report: %s",
                violations.size(), report.getAbsolutePath());
        if (failOnViolation.get()) {
            throw new GradleException(message);
        }
        getLogger().warn(message);
    }

    @Input
    public Property<Boolean> getCheckerEnabled() {
        return enabled;
    }

    @Input
    public Property<Boolean> getFailOnViolation() {
        return failOnViolation;
    }

    @Input
    public Property<Boolean> getFailOnNoKafkaDependency() {
        return failOnNoKafkaDependency;
    }

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Open the report at the path in the message and read each violation to see which internal symbol is referenced and from where.
  2. Replace the internal-API call with the supported public-API equivalent (e.g. use org.apache.kafka.clients.consumer.ConsumerRecord fields instead of internal helpers).
  3. If the usage is genuinely necessary and justified, annotate the offending element with @SuppressKafkaInternalApiUsage(reason = "...") per KIP-1265 — and make sure the reason text is non-empty, otherwise the build still warns about unjustified suppressions.
  4. If the check is producing false positives during a migration, set kafkaInternalApiChecker.failOnViolation = false temporarily to keep the build green while the report is triaged (do not leave it off).

Example fix

// before
import org.apache.kafka.common.utils.Utils;

class MyClient {
  int port = Utils.portFromUri(uri); // internal API -> violation
}

// after — use the public API
import org.apache.kafka.clients.CommonClientConfigs;

class MyClient {
  int port = Integer.parseInt(config.getString(CommonClientConfigs.PORT_CONFIG));
}
Defensive patterns

Strategy: validation

Validate before calling

// Gate violations only in CI; warn in local dev so you can triage before the build breaks
tasks.named<org.apache.kafka.gradle.KafkaInternalApiCheckerTask>("kafkaInternalApiChecker").configure {
    failOnViolation = (System.getenv("CI") != null)
}
// Editor/CI pre-scan for known internal package imports before invoking the plugin
// rg -n 'org\.apache\.kafka\.[A-Za-z0-9_.]+\.internal' src/main

Prevention

When it happens

Trigger: reportResults() at line 148: violations.isEmpty() is false and failOnViolation.get() is true. Produced when compiled project bytecode references internal Kafka symbols (e.g. org.apache.kafka.common.utils.Bytes, anything under impl packages, or non-@InterfaceAudience.Public classes) and no @SuppressKafkaInternalApiUsage annotation justifies the usage.

Common situations: Code reaches into Kafka internals (utils, protocol classes, *Impl) because the public API lacks a needed method; an upgrade to a newer Kafka release removed @InterfaceAudience.Public from a previously-public symbol; copy-pasted sample code that uses internal helpers; a refactor that promotes an internal class into a public signature without re-annotating it.

Related errors


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