brettwooldridge/HikariCP · error · IllegalStateException
MetricRegistry can only be set one time
Error message
MetricRegistry can only be set one time
What it means
setMetricRegistry() on HikariDataSource refuses to change the metric registry once the pool has been started and a registry was already set. HikariCP wires metrics into the live pool at startup, so re-assigning the registry afterwards would silently produce wrong metrics; it throws IllegalStateException instead.
Source
Thrown at src/main/java/com/zaxxer/hikari/HikariDataSource.java:241
return false;
}
// ***********************************************************************
// HikariConfigMXBean methods
// ***********************************************************************
/** {@inheritDoc} */
@Override
public void setMetricRegistry(Object metricRegistry)
{
var isAlreadySet = getMetricRegistry() != null;
super.setMetricRegistry(metricRegistry);
var p = pool;
if (p != null) {
if (isAlreadySet) {
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");View on GitHub (pinned to a4d93f4f85)
Solutions
- Set the metric registry once, before the first getConnection() (i.e., before pool initialization)
- Remove duplicate configuration paths that set the registry (check both your code and framework autoconfiguration)
- If you must change registries, close the DataSource, create a new one configured correctly, and swap it
- Set spring.datasource.hikari.* properties (or the equivalent) declaratively so ordering is deterministic
Example fix
// before HikariDataSource ds = new HikariDataSource(config); ds.getConnection(); // pool starts ds.setMetricRegistry(registry); // second set -> IllegalStateException // after config.setMetricRegistry(registry); // before startup HikariDataSource ds = new HikariDataSource(config);
Defensive patterns
Strategy: validation
Validate before calling
// set registry once, before pool start
HikariConfig cfg = new HikariConfig();
cfg.setMetricRegistry(registry);
// assert getMetricRegistry() == null before calling setter on an existing DS
if (ds.getMetricRegistry() != null) { /* skip: already bound */ } Prevention
- Assign metric registries in one place, before first getConnection
- Never rebind registries on a live pool; rebuild instead
- Watch for framework autoconfig also setting the registry
When it happens
Trigger: Calling setMetricRegistry(...) twice while the pool is running; a framework (Spring Boot metrics, Dropwizard) injecting the registry in a @PostConstruct that runs after the pool lazily started; reconfiguring metrics at runtime via JMX/actuator.
Common situations: Spring Boot actuator + custom MetricRegistry bean, micrometer migration re-binding registries, dev hot-reload re-running configuration against the same live DataSource.
Related errors
- MetricsTrackerFactory 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/5a04a54321e95916.
Report an issue: GitHub.