apache/kafka · error · GradleException

Found internal API usage violations. See report

Error message

Found %d internal API usage violations. See report: %s

What it means

GradleException thrown by KafkaInternalApiCheckerTask.reportResults when the bytecode scan found one or more references to internal Kafka APIs and failOnViolation is true (the default). The message includes the violation count and the path to the text report. This is the task's primary failure mode — it is signalling real illegal usage of internal API.

Solutions

  1. Open the report at the path named in the message and read each PublicApiViolation to see which internal symbol is referenced.
  2. Replace the internal API usage with the documented public equivalent (e.g. use Admin/Producer/Consumer APIs instead of package-private helpers).
  3. If the usage is intentional and justified, annotate it with @SuppressKafkaInternalApiUsage(reason = "...") — KIP-1265 requires a non-empty reason.
  4. Temporarily set kafkaInternalApiChecker.failOnViolation = false to make it a warning while you triage (do not ship this way).

Example fix

// before — references internal helper
import org.apache.kafka.common.internals.PluginUtils;
PluginUtils.pluginClassLoader(...);
// after — annotate with justification per KIP-1265
@SuppressKafkaInternalApiUsage(reason = "Classloader isolation in connector X, no public equivalent")
PluginUtils.pluginClassLoader(...);
Defensive patterns

Strategy: validation

Validate before calling

// Use the checker's dry-run: set failOnViolation=false in a 'triage' run, parse the report, then fix or suppress.
kafkaInternalApiChecker.failOnViolation = false

Try / catch

try { tasks.checkInternalApiUsage() } catch (GradleException e) { if (e.message.contains('internal API usage violations')) { /* read report, suppress with reason, or migrate API */ } else throw e }

Prevention

When it happens

Trigger: violations list is non-empty after PublicApiChecker.checkBytecode (line 116) and failOnViolation.get() is true (line 148). Triggered when compiled .class files in the configured classDirs reference package-private or @InternalApi-marked Kafka symbols.

Common situations: Consuming org.apache.kafka.* internal package types, accessing classes marked with the internal API annotation, depending on a Kafka type that was public in one version but moved to internal in another, or forgetting to annotate legitimate usage with @SuppressKafkaInternalApiUsage.

Related errors


AI-assisted analysis of apache/kafka@996fb4585a (2026-08-11). Data as JSON: /api/errors/e54f4969b35141d8. Report an issue: GitHub.

Appendix: 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 996fb4585a)