Usamos cookies essenciais para login e armazenamento local para suas preferências. Para métricas de uso, usamos o Google Analytics 4 — você pode recusar sem perder nada do produto. Saber mais

ThreadMineThreadMine
Voltar

Mensagem de erro

HikariPool-1 - Connection is not available, request timed out after 30000ms

Resposta rápida

Causa provávelTodas as conexões do pool estavam em uso. Quem espera é vítima; quem segura as conexões é a causa.

Próximo passoNão reinicie: apaga a prova. Tire um thread dump.

Thread dump

jcmd <pid> Thread.print -l > dump.txt
Analisar meu dump agora

A linha do log (HikariCP 6.3.3)

2026-10-30 14:02:11.482 ERROR [http-nio-8080-exec-10] Request processing failed
java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30000ms (total=10, active=10, idle=0, waiting=12)
	at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:714)
	at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:184)
	at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:142)
	at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:99)

O que a mensagem significa

HikariPool-1 é o poolName padrão. Uma thread chamou getConnection(), esperou o connectionTimeout (30000 ms por padrão) e não recebeu conexão. O HikariCP lança então java.sql.SQLTransientConnectionException.

Desde o HikariCP 5.1.0 a mensagem termina com as estatísticas do pool, e é a primeira coisa a ler:

  • active igual a total, idle=0, waiting maior que 0: o pool está esgotado. Todas as conexões estão em uso e as requisições formam fila. Esta página trata deste caso.
  • total=0 ou active=0: o pool nunca conseguiu uma conexão, então o banco está inacessível ou recusando. Leia o Caused by abaixo da mensagem. O thread dump não ajuda aqui.

Causas comuns

O maximumPoolSize padrão é 10, mas um pool desse tamanho raramente é a causa raiz. Procure quem segura as conexões por tempo demais:

  1. Query lenta ou lock no banco. Cada requisição segura a conexão enquanto espera.
  2. Chamada HTTP externa dentro de @Transactional. A conexão fica emprestada enquanto a thread espera uma API de parceiro.
  3. Open Session in View. Ligado por padrão no Spring Boot, mantém a sessão de persistência aberta durante a requisição inteira, e em algumas configurações a conexão fica emprestada junto, inclusive durante a renderização da resposta.
  4. Connection leak. Uma conexão obtida e nunca fechada.
  5. Uma segunda conexão com a primeira na mão. Um REQUIRES_NEW ou uma chamada aninhada que pega outra conexão. Todas as threads acabam em getConnection e ninguém está no driver.
  6. Um pool pequeno de verdade para a concorrência. Possível, mas é a última hipótese, não a primeira.

Capture a evidência

Um dump mostra um instante. Tire dois ou três, com 10 segundos de intervalo, para ver quais threads ficam no mesmo lugar:

Três dumps, 10 segundos de intervalo

for i in 1 2 3; do jcmd <pid> Thread.print -l > dump-$i.txt; sleep 10; done

O jstack -l <pid> funciona do mesmo jeito. Para containers, Windows e kill -3, veja como capturar um thread dump.

Tem o dump? Cole e veja quais threads seguram as conexões.

Analisar meu dump agora

Dump com dados sensíveis? Anonimize antes com o tm-anon.

Como aparece no dump

Este é um dump real da nossa reprodução: JDK 25, HikariCP 6.3.3, um pool de 4 conexões e 20 threads de requisição. Dezesseis threads esperam por uma conexão, todas com esta stack:

Esperando uma conexão

"http-nio-8080-exec-10" #39 [45876] prio=5 os_prio=0 cpu=0.00ms elapsed=5.30s tid=0x00000083ade64510 nid=45876 waiting on condition  [0x00000083b00ce000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at jdk.internal.misc.Unsafe.park(java.base@25.0.2/Native Method)
	- parking to wait for  <0x00000006219a0920> (a java.util.concurrent.SynchronousQueue$Transferer)
	at java.util.concurrent.locks.LockSupport.parkNanos(java.base@25.0.2/LockSupport.java:408)
	at java.util.concurrent.LinkedTransferQueue$DualNode.await(java.base@25.0.2/LinkedTransferQueue.java:452)
	at java.util.concurrent.LinkedTransferQueue.xfer(java.base@25.0.2/LinkedTransferQueue.java:613)
	at java.util.concurrent.SynchronousQueue.xfer(java.base@25.0.2/SynchronousQueue.java:235)
	at java.util.concurrent.SynchronousQueue.poll(java.base@25.0.2/SynchronousQueue.java:338)
	at com.zaxxer.hikari.util.ConcurrentBag.borrow(ConcurrentBag.java:162)
	at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:160)
	at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:142)
	at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:99)
	...

Essas threads são as vítimas. As culpadas são as que não estão em HikariPool.getConnection: três rodavam uma query no driver, e esta segurava uma conexão enquanto chamava um serviço externo (simulado aqui com um sleep):

Segurando uma conexão em outro ponto

"http-nio-8080-exec-4" #33 [60220] prio=5 os_prio=0 cpu=0.00ms elapsed=5.58s tid=0x00000083ade5fec0 nid=60220 waiting on condition  [0x00000083af9ce000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleepNanos0(java.base@25.0.2/Native Method)
	at java.lang.Thread.sleepNanos(java.base@25.0.2/Thread.java:509)
	at java.lang.Thread.sleep(java.base@25.0.2/Thread.java:540)
	at Repro$PartnerClient.chargeCard(Repro.java:9)
	...

O ThreadMine lê esse padrão e o reporta como um achado de pool de conexões:

Crítico

Pool de conexões esgotado: 16 threads aguardando conexão do HikariCP

16 threads

Todas as conexões do pool estão em uso. Olhe para as threads que seguram as conexões, não para as que esperam: em query, ou presas em outro ponto com a conexão aberta.

Para fazer à mão, conte as threads em getConnection e leia as stacks de todas as outras.

Como corrigir

Corrija a causa que o dump apontou. Aumentar o tamanho do pool vem por último.

Query lenta ou lock

Corrija a query ou o lock. Adicione um timeout de statement para que uma query ruim não segure a conexão para sempre: @Transactional(timeout = 5) no Spring, ou statement_timeout no PostgreSQL.

Chamada externa dentro da transação

Tire a chamada do método @Transactional, para a conexão ser emprestada só durante o trabalho no banco.

Open Session in View

Defina spring.jpa.open-in-view=false e carregue o que a view precisa dentro do service.

Leak

Defina spring.datasource.hikari.leak-detection-threshold (por exemplo 20000, em ms). O HikariCP registra a stack do código que pegou uma conexão e não a devolveu a tempo. Depois feche com try-with-resources.

Falha lenta

O spring.datasource.hikari.connection-timeout decide quanto uma requisição espera. Diminuí-lo faz a falha chegar mais rápido, e não libera nada.

Aumente o pool por último

O spring.datasource.hikari.maximum-pool-size ajuda quando as conexões são seguradas por um tempo normal e a concorrência realmente é maior. Confira o limite do banco antes de aumentar.

Mais sobre ler threads numa aplicação travada: Spring Boot stuck threads.

Perguntas frequentes

O que significa "HikariPool-1 - Connection is not available"?

Uma thread chamou getConnection() e o pool não teve conexão livre durante todo o connectionTimeout, 30000 ms por padrão. HikariPool-1 é o nome do pool. A exceção é java.sql.SQLTransientConnectionException. Os números entre parênteses (total, active, idle, waiting) dizem se o pool está cheio ou se o banco está inacessível.

Devo aumentar o maximumPoolSize?

Não primeiro. O padrão é 10. Se as conexões estão presas por uma query lenta, um leak ou uma chamada externa dentro de uma transação, um pool maior só empurra o limite e coloca mais carga no banco. Ache quem segura as conexões com um thread dump, corrija isso e aumente o tamanho por último.

Qual é o timeout padrão?

O connectionTimeout é 30000 ms por padrão, por isso a mensagem diz "after 30000ms". No Spring Boot a propriedade é spring.datasource.hikari.connection-timeout. Um valor menor faz as requisições falharem mais rápido, mas não libera as conexões.

Como acho quem está segurando as conexões?

Tire um thread dump e olhe as threads que não estão em HikariPool.getConnection. As que estão numa chamada do driver JDBC rodam uma query. As que estão em outro lugar, por exemplo esperando uma chamada HTTP, podem segurar uma conexão que já pegaram. Para pegar um leak, configure leak-detection-threshold, e o HikariCP registra a stack do código que pegou uma conexão e não a devolveu a tempo.

O problema é o banco?

Só às vezes. Se as estatísticas mostram total=0 ou active=0, o pool não alcança o banco: leia o Caused by da exceção, porque o dump não ajuda. Se active é igual a total, idle=0 e waiting é maior que zero, o pool está esgotado, e a causa costuma estar na aplicação ou numa query lenta.

Tem o dump do pool travado?

Cole e veja quais threads seguram as conexões. Sem cadastro para o primeiro dump.