Mensaje de error
PKIX path validation failed: java.security.cert.CertPathValidatorException: validity check failed
También se muestra como
- javax.net.ssl.SSLHandshakeException: (certificate_expired) PKIX path validation failed: java.security.cert.CertPathValidatorException: validity check failed
JDK 21 y posteriores anteponen la alerta TLS: «(certificate_expired) PKIX path validation failed: …». La línea de la causa raíz es «java.security.cert.CertificateExpiredException: NotAfter: <date>» (o CertificateNotYetValidException: NotBefore: <date>), con la fecha en la zona horaria de la JVM.
Java (JSSE) — SSLHandshakeException caused by CertPathValidatorException / CertificateExpiredException
Qué significa
Java construyó una ruta de certificación hasta un ancla de confianza, pero su validación no superó la comprobación de fechas: un certificado de la ruta está fuera de su período de validez según la hora actual de la JVM. Que diga «path validation» (y no «path building») significa que la confianza estaba bien; las fechas, no. La CertificateExpiredException o CertificateNotYetValidException anidada indica qué límite se incumple.
Por qué ocurre
El certificado del servidor (o un intermedio) está caducado
frecuenteLa renovación no se hizo o el certificado renovado no está desplegado en el endpoint con el que habla Java (a menudo un balanceador de carga interno o un servidor Java con su propio almacén de claves).
La cadena se construyó a través de un certificado caducado de un almacén de confianza personalizado
ocasionalLos almacenes de confianza que fijan directamente un intermedio antiguo o un certificado de servidor siguen validando con él después de que caduque.
El reloj del host de la JVM está mal
ocasionalLas máquinas virtuales y los contenedores cuyo reloj del host se desvió pueden hacer que certificados vigentes parezcan caducados o aún no válidos.
Un certificado recién emitido y un reloj atrasado
raraLos certificados válidos desde «ahora» fallan en clientes que van unos minutos atrasados; por eso la mayoría de las CA fijan notBefore ligeramente en el pasado, pero las CA privadas a menudo no lo hacen.
Cómo solucionarlo
- 1.
Leer la causa más interna
La fecha NotAfter o NotBefore te dice si un certificado caducó o si el reloj está desajustado.
text Caused by: java.security.cert.CertificateExpiredException: NotAfter: Tue Apr 01 00:00:00 UTC 2025 -> a certificate in the chain expired on that date Caused by: java.security.cert.CertificateNotYetValidException: NotBefore: ... -> not valid yet: check the clock of this machine - 2.
Comprobar cada certificado que envía el servidor
Imprime la fecha de fin de cada certificado de la cadena servida y sustituye el que haya caducado.
bash echo | openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts 2>/dev/null \ | awk '/BEGIN CERT/{n++; f="c" n ".pem"} /BEGIN CERT/,/END CERT/{print > f}' for f in c*.pem; do openssl x509 -in "$f" -noout -subject -enddate; done - 3.
Limpiar los almacenes de confianza personalizados
Lista las entradas del almacén de confianza con su validez y elimina o sustituye los certificados caducados que se fijaron en él.
bash # Expired or pinned certificates in a custom trust store keytool -list -v -keystore app-truststore.p12 -storepass changeit | grep -E 'Alias name|Valid until|Owner' keytool -delete -alias old-corp-root -keystore app-truststore.p12 -storepass changeit