apache/iceberg · warning

Unable to load metrics class: '{}', falling back to null met

Error message

Unable to load metrics class: '{}', falling back to null metrics

What it means

ADLSFileIO.initMetrics() reflectively constructs the ADLS metrics context class at initialize(). If the class is missing (NoClassDefFoundError), has no matching constructor, or doesn't implement MetricsContext, it warns and falls back to null metrics — the FileIO still works, just without metrics instrumentation.

Source

Thrown at azure/src/main/java/org/apache/iceberg/azure/adlsv2/ADLSFileIO.java:188

    initMetrics(properties);
    this.azureProperties
        .vendedAdlsCredentialProvider()
        .ifPresent(provider -> this.vendedAdlsCredentialProvider = provider);
  }

  @SuppressWarnings("CatchBlockLogException")
  private void initMetrics(Map<String, String> props) {
    // Report Hadoop metrics if Hadoop is available
    try {
      DynConstructors.Ctor<MetricsContext> ctor =
          DynConstructors.builder(MetricsContext.class)
              .hiddenImpl(DEFAULT_METRICS_IMPL, String.class)
              .buildChecked();
      MetricsContext context = ctor.newInstance("adls");
      context.initialize(props);
      this.metrics = context;
    } catch (NoClassDefFoundError | NoSuchMethodException | ClassCastException e) {
      LOG.warn(
          "Unable to load metrics class: '{}', falling back to null metrics", DEFAULT_METRICS_IMPL);
    }
  }

  @Override
  public void deleteFiles(Iterable<String> pathsToDelete) throws BulkDeletionFailureException {
    // Azure batch operations are not supported in all cases, e.g. with a user
    // delegation SAS token, so avoid using it for now

    AtomicInteger failureCount = new AtomicInteger();
    Tasks.foreach(pathsToDelete)
        .executeWith(ThreadPools.getWorkerPool())
        .noRetry()
        .suppressFailureWhenFinished()
        .onFailure(
            (file, exc) -> {
              failureCount.incrementAndGet();
              LOG.warn("Failed to delete file {}", file, exc);

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Add the module providing the default metrics implementation to the classpath
  2. Check for dependency shading/conflicts that drop the metrics classes
  3. Align library versions so the constructor signature matches what ADLSFileIO expects
  4. If metrics are intentionally unwanted, ignore the warning

Example fix

// before (gradle)
implementation 'org.apache.iceberg:iceberg-azure'
// after
implementation 'org.apache.iceberg:iceberg-azure'
implementation 'org.apache.iceberg:iceberg-azure-bundle' // pulls metrics impl
Defensive patterns

Strategy: fallback

Validate before calling

try {
  Class.forName("org.apache.iceberg.metrics.LoggingMetricsContext");
} catch (ClassNotFoundException e) {
  LOG.warn("ADLS metrics impl missing from classpath; add iceberg-azure-bundle");
}

Prevention

When it happens

Trigger: Initializing ADLSFileIO without the metrics implementation on the classpath (e.g. the module providing DEFAULT_METRICS_IMPL is excluded), or with an incompatible version whose constructor signature changed.

Common situations: Shaded/minimal deployments missing the metrics module; dependency conflicts after upgrades; custom classpaths in Spark/Flink distributions.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/94f249eeaef558d0. Report an issue: GitHub.