brettwooldridge/HikariCP · error · IllegalStateException
MetricsTrackerFactory can only be set one time
Error message
MetricsTrackerFactory can only be set one time
What it means
setMetricsTrackerFactory() can only be assigned once before/while the pool starts; if a factory is already set and the pool exists, HikariDataSource throws IllegalStateException. The tracker factory is bound into the pool's metrics lifecycle at startup and cannot be swapped afterwards.
Source
Thrown at src/main/java/com/zaxxer/hikari/HikariDataSource.java:259
throw new IllegalStateException("MetricRegistry can only be set one time");
}
else {
p.setMetricRegistry(super.getMetricRegistry());
}
}
}
/** {@inheritDoc} */
@Override
public void setMetricsTrackerFactory(MetricsTrackerFactory metricsTrackerFactory)
{
var isAlreadySet = getMetricsTrackerFactory() != null;
super.setMetricsTrackerFactory(metricsTrackerFactory);
var p = pool;
if (p != null) {
if (isAlreadySet) {
throw new IllegalStateException("MetricsTrackerFactory can only be set one time");
}
else {
p.setMetricsTrackerFactory(super.getMetricsTrackerFactory());
}
}
}
/** {@inheritDoc} */
@Override
public void setHealthCheckRegistry(Object healthCheckRegistry)
{
var isAlreadySet = getHealthCheckRegistry() != null;
super.setHealthCheckRegistry(healthCheckRegistry);
var p = pool;
if (p != null) {
if (isAlreadySet) {
throw new IllegalStateException("HealthCheckRegistry can only be set one time");View on GitHub (pinned to a4d93f4f85)
Solutions
- Set metricsTrackerFactory exactly once, before first connection acquisition
- Ensure metricRegistry and metricsTrackerFactory are not both being set by different components
- To replace the factory, tear down and rebuild the DataSource
- Configure it via HikariConfig before constructing HikariDataSource(config)
Example fix
// before ds.setMetricsTrackerFactory(factoryA); ds.setMetricsTrackerFactory(factoryB); // IllegalStateException // after HikariConfig cfg = new HikariConfig(); cfg.setMetricsTrackerFactory(factoryB); // single assignment pre-start HikariDataSource ds = new HikariDataSource(cfg);
Defensive patterns
Strategy: validation
Validate before calling
if (ds.getMetricsTrackerFactory() == null && ds.getMetricRegistry() == null) {
ds.setMetricsTrackerFactory(factory);
} Prevention
- Set metricsTrackerFactory exactly once pre-start
- Do not mix metricRegistry and metricsTrackerFactory on the same pool
- Centralize metrics wiring in one configuration class
When it happens
Trigger: Calling setMetricsTrackerFactory(...) twice on a live pool; specifying both metricRegistry and metricsTrackerFactory (framework may set one, your code the other); Prometheus/micrometer glue re-registering the factory on refresh.
Common situations: Custom MetricsTrackerFactory for Prometheus, repeated initialization during Spring context refresh, actuator endpoint that rebinds metrics.
Related errors
- MetricRegistry can only be set one time
- cannot use setMetricsTrackerFactory() and setMetricRegistry(
- cannot use setMetricRegistry() and setMetricsTrackerFactory(
- Class must be instance of com.codahale.metrics.MetricRegistr
- The configuration of the pool is sealed once started. Use Hi
AI-assisted analysis of brettwooldridge/HikariCP@a4d93f4f85 (2026-08-14).
Data as JSON: /api/errors/4b9680b9a1deea44.
Report an issue: GitHub.