{"record":{"id":"9fc650fcfea64b46","repo":"brettwooldridge/HikariCP","slug":"class-must-be-instance-of-com-codahale-metrics-met","errorCode":null,"errorMessage":"Class must be instance of com.codahale.metrics.MetricRegistry, io.dropwizard.metrics5.MetricRegistry, or io.micrometer.core.instrument.MeterRegistry","messagePattern":"Class must be instance of com\\.codahale\\.metrics\\.MetricRegistry, io\\.dropwizard\\.metrics5\\.MetricRegistry, or io\\.micrometer\\.core\\.instrument\\.MeterRegistry","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/zaxxer/hikari/HikariConfig.java","lineNumber":684,"sourceCode":"\n   /**\n    * Set a MetricRegistry instance to use for registration of metrics used by HikariCP.\n    *\n    * @param metricRegistry the MetricRegistry instance to use\n    */\n   public void setMetricRegistry(Object metricRegistry)\n   {\n      if (metricsTrackerFactory != null) {\n         throw new IllegalStateException(\"cannot use setMetricRegistry() and setMetricsTrackerFactory() together\");\n      }\n\n      if (metricRegistry != null) {\n         metricRegistry = getObjectOrPerformJndiLookup(metricRegistry);\n\n         if (!safeIsAssignableFrom(metricRegistry, \"com.codahale.metrics.MetricRegistry\")\n             && !(safeIsAssignableFrom(metricRegistry, \"io.dropwizard.metrics5.MetricRegistry\"))\n             && !(safeIsAssignableFrom(metricRegistry, \"io.micrometer.core.instrument.MeterRegistry\"))) {\n            throw new IllegalArgumentException(\"Class must be instance of com.codahale.metrics.MetricRegistry, \" +\n               \"io.dropwizard.metrics5.MetricRegistry, or io.micrometer.core.instrument.MeterRegistry\");\n         }\n      }\n\n      this.metricRegistry = metricRegistry;\n   }\n\n   /**\n    * Get the HealthCheckRegistry that will be used for registration of health checks by HikariCP.  Currently only\n    * Codahale/DropWizard is supported for health checks.\n    *\n    * @return the HealthCheckRegistry instance that will be used\n    */\n   public Object getHealthCheckRegistry()\n   {\n      return healthCheckRegistry;\n   }\n","sourceCodeStart":666,"sourceCodeEnd":702,"githubUrl":"https://github.com/brettwooldridge/HikariCP/blob/a4d93f4f85517f90e632b795486d7102e933d7ff/src/main/java/com/zaxxer/hikari/HikariConfig.java#L666-L702","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass a Micrometer MeterRegistry (recommended, wraps everything) — e.g. Metrics.globalRegistry or an injected MeterRegistry","If using Dropwizard, pass the actual com.codahale.metrics.MetricRegistry or io.dropwizard.metrics5.MetricRegistry instance","For Prometheus exposure, add micrometer-registry-prometheus and pass its PrometheusMeterRegistry — never the raw CollectorRegistry","If the value comes from JNDI/properties, verify what the name actually resolves to at runtime before wiring it"],"exampleFix":"// before\nconfig.setMetricRegistry(prometheusCollectorRegistry); // IllegalArgumentException\n\n// after\n// with micrometer-registry-prometheus on the classpath\nPrometheusMeterRegistry promRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);\nconfig.setMetricRegistry(promRegistry);","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static boolean isSupportedMetricRegistry(Object o) {\n   return o instanceof io.micrometer.core.instrument.MeterRegistry\n       || o instanceof com.codahale.metrics.MetricRegistry\n       || o instanceof io.dropwizard.metrics5.MetricRegistry;\n}\n// use: if (isSupportedMetricRegistry(candidate)) config.setMetricRegistry(candidate);","tryCatchPattern":"catch (IllegalArgumentException e) {\n   log.error(\"Unsupported metric registry type: {} — pass a Micrometer MeterRegistry\", candidate.getClass(), e);\n}","preventionTips":["Prefer Micrometer MeterRegistry as the universal adapter","Do not pass raw Prometheus CollectorRegistry — wrap it with micrometer-registry-prometheus","When the value comes from JNDI/properties, resolve and type-check it before wiring"],"tags":["hikaricp","configuration","metrics","micrometer","dropwizard","type-check"],"backgroundTag":null,"analyzedSha":"a4d93f4f85517f90e632b795486d7102e933d7ff","analyzedAt":"2026-08-14T12:11:37.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}