brettwooldridge/HikariCP · error · IllegalArgumentException

Class must be instance of com.codahale.metrics.MetricRegistr

Error message

Class must be instance of com.codahale.metrics.MetricRegistry, io.dropwizard.metrics5.MetricRegistry, or io.micrometer.core.instrument.MeterRegistry

What it means

When setMetricRegistry(Object) receives a non-null object, HikariCP first resolves it (unwrapping/JNDI lookup via getObjectOrPerformJndiLookup) and then verifies it is a com.codahale.metrics.MetricRegistry, io.dropwizard.metrics5.MetricRegistry, or io.micrometer.core.instrument.MeterRegistry. Anything else throws IllegalArgumentException — HikariCP has reflective (not compile-time) support for these libraries, so it must type-check at runtime.

Source

Thrown at src/main/java/com/zaxxer/hikari/HikariConfig.java:684

   /**
    * Set a MetricRegistry instance to use for registration of metrics used by HikariCP.
    *
    * @param metricRegistry the MetricRegistry instance to use
    */
   public void setMetricRegistry(Object metricRegistry)
   {
      if (metricsTrackerFactory != null) {
         throw new IllegalStateException("cannot use setMetricRegistry() and setMetricsTrackerFactory() together");
      }

      if (metricRegistry != null) {
         metricRegistry = getObjectOrPerformJndiLookup(metricRegistry);

         if (!safeIsAssignableFrom(metricRegistry, "com.codahale.metrics.MetricRegistry")
             && !(safeIsAssignableFrom(metricRegistry, "io.dropwizard.metrics5.MetricRegistry"))
             && !(safeIsAssignableFrom(metricRegistry, "io.micrometer.core.instrument.MeterRegistry"))) {
            throw new IllegalArgumentException("Class must be instance of com.codahale.metrics.MetricRegistry, " +
               "io.dropwizard.metrics5.MetricRegistry, or io.micrometer.core.instrument.MeterRegistry");
         }
      }

      this.metricRegistry = metricRegistry;
   }

   /**
    * Get the HealthCheckRegistry that will be used for registration of health checks by HikariCP.  Currently only
    * Codahale/DropWizard is supported for health checks.
    *
    * @return the HealthCheckRegistry instance that will be used
    */
   public Object getHealthCheckRegistry()
   {
      return healthCheckRegistry;
   }

View on GitHub (pinned to a4d93f4f85)

Solutions

  1. Pass a Micrometer MeterRegistry (recommended, wraps everything) — e.g. Metrics.globalRegistry or an injected MeterRegistry
  2. If using Dropwizard, pass the actual com.codahale.metrics.MetricRegistry or io.dropwizard.metrics5.MetricRegistry instance
  3. For Prometheus exposure, add micrometer-registry-prometheus and pass its PrometheusMeterRegistry — never the raw CollectorRegistry
  4. If the value comes from JNDI/properties, verify what the name actually resolves to at runtime before wiring it

Example fix

// before
config.setMetricRegistry(prometheusCollectorRegistry); // IllegalArgumentException

// after
// with micrometer-registry-prometheus on the classpath
PrometheusMeterRegistry promRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
config.setMetricRegistry(promRegistry);
Defensive patterns

Strategy: type-guard

Type guard

static boolean isSupportedMetricRegistry(Object o) {
   return o instanceof io.micrometer.core.instrument.MeterRegistry
       || o instanceof com.codahale.metrics.MetricRegistry
       || o instanceof io.dropwizard.metrics5.MetricRegistry;
}
// use: if (isSupportedMetricRegistry(candidate)) config.setMetricRegistry(candidate);

Try / catch

catch (IllegalArgumentException e) {
   log.error("Unsupported metric registry type: {} — pass a Micrometer MeterRegistry", candidate.getClass(), e);
}

Prevention

When it happens

Trigger: Passing a generic Object from configuration/properties that resolves to the wrong type, e.g. a String JNDI name that resolves to a HealthCheckRegistry, a Prometheus CollectorRegistry, a Micrometer Clock, or a plain map; passing a class instead of an instance; a JNDI lookup returning an unexpected object type.

Common situations: Using Prometheus directly (CollectorRegistry is NOT a Micrometer MeterRegistry — you need micrometer-registry-prometheus to wrap it); binding the wrong JNDI name in an app server; version drift where the registry class moved between packages (metrics-core 2.x codahale vs 3/4/5 dropwizard); scripted/XML config where the property is a string resolved at runtime.

Related errors


AI-assisted analysis of brettwooldridge/HikariCP@a4d93f4f85 (2026-08-14). Data as JSON: /api/errors/9fc650fcfea64b46. Report an issue: GitHub.