Ошибка PKIX path building failed: unable to find valid certification path to requested target означает, что Java не смогла построить доверенную цепочку сертификата сервера. Для исправления я сначала проверяю сертификаты и фактическую Java процесса, затем добавляю нужный доверенный сертификат в используемое хранилище. Отключать проверку TLS для этого не требуется. Механизм выбора хранилища описан в JSSE Reference Guide для Java 21.
Сертификаты и полную присланную сервером цепочку можно получить по инструкции «Скачать сертификат сайта». Скачивание сертификата само по себе не удостоверяет его подлинность: перед добавлением доверия нужно сверить SHA-256 с владельцем инфраструктуры или другим доверенным источником. Особенно это важно для корневого CA, доверие к которому распространяется на выданные им сертификаты. Предупреждения keytool об импорте доверенных сертификатов.
Импорт в существующее хранилище
Сначала нужно определить JDK именно того процесса, который соединяется с сервером. В IntelliJ IDEA для сборки это Settings → Build, Execution, Deployment → Build Tools → Gradle → Gradle JVM, а путь зарегистрированного JDK виден в Project Structure → SDKs. Project SDK, Java терминала и Java Gradle могут отличаться.
Команда импорта через keytool:
keytool -importcert -file cert_name.crt -keystore keystore_path -alias alias_certГде
cert_name.crt- имя сертификата; расширение само по себе не определяет форматkeystore_path- путь до хранилища сертификатов в JVM- Пример:
jdk_path/lib/security/cacerts
- Пример:
alias_cert- алиас для сертификата
Пароль вводится по запросу; стандартный пароль поставляемого JDK cacerts часто равен changeit, но его могли изменить. -storepass позволяет передать пароль явно. Параметр -noprompt из старого примера убран: при первом добавлении доверия полезно проверить данные сертификата и подтвердить импорт вручную. Параметры keytool.
Проверка, что сертификат был добавлен:
keytool -list -keystore keystore_path -alias alias_certДля подробностей и SHA-256 добавить -v. Успех — запись с ожидаемым alias, типом trustedCertEntry и нужным отпечатком, а не только отсутствие запроса пароля.
Пользовательское хранилище без прав администратора
Если JDK установлен в защищённый каталог, например Program Files, обычный пользователь не сможет записать его lib/security/cacerts. Для Gradle можно скопировать стандартное хранилище в доступную папку, добавить сертификаты в копию и явно выбрать её. Копирование сохраняет стандартные доверенные CA, которые нужны для других HTTPS-ресурсов; созданное с нуля хранилище их не содержит. Java поддерживает выбор отдельного файла через javax.net.ssl.trustStore. JSSE: настройка truststore.
Пример для Git Bash в Windows
Все пути ниже учебные: JDK и пользовательский каталог нужно заменить фактическими. cp -i спрашивает перед перезаписью: существующее настроенное хранилище не следует заменять свежей копией без проверки.
cp -i "/c/Program Files/Java/jdk-21/lib/security/cacerts" "$HOME/.gradle/custom-cacerts"
"/c/Program Files/Java/jdk-21/bin/keytool.exe" -importcert -file "$HOME/Downloads/corporate-root.crt" -keystore "$HOME/.gradle/custom-cacerts" -alias "corporate-root"
"/c/Program Files/Java/jdk-21/bin/keytool.exe" -list -v -keystore "$HOME/.gradle/custom-cacerts" -alias "corporate-root"При ошибке Access denied / Отказано в доступе после сообщения Certificate was added to keystore запись на диск не считается успешной. Итоговую проверку нужно выполнить отдельным -list по тому же файлу.
Подключение к Gradle
В Gradle user home, указанном в IDEA, открыть или создать gradle.properties. По умолчанию это пользовательский каталог .gradle. Существующие настройки сохранить; повторяющиеся ключи не добавлять. Для учебного пользователя developer:
systemProp.javax.net.ssl.trustStore=C:/Users/developer/.gradle/custom-cacerts
systemProp.javax.net.ssl.trustStorePassword=changeitЭто файл gradle.properties, а не gradle.properties.txt: в Windows нужно проверить расширение. Для пути внутри properties использую прямые слеши; обратные слеши в Java properties требуют экранирования. trustStorePassword передаёт существующий пароль хранилища, а не устанавливает новый. changeit здесь относится только к копии стандартного cacerts, а не к учётным данным сервера. Поддержка systemProp.* и расположение пользовательского файла описаны в Gradle Build Environment.
После изменения хранилища или его параметров нужно перезапустить использующую его Java. Для IDEA: закрыть приложение, остановить Gradle daemon и открыть IDEA заново. Команда зависит от оболочки и фактического пути установленного Gradle:
# Git Bash
"/c/tools/gradle/bin/gradle.bat" --stop# PowerShell, в том числе внутри терминала IDEA
& "C:\tools\gradle\bin\gradle.bat" --stopЗатем выполнить Reload All Gradle Projects. Старый daemon может сохранять SSL-состояние; Gradle относит параметры truststore к неизменяемым свойствам JVM daemon. Выходить из Windows для обычного изменения truststore не требуется.
Если PKIX остался
- Проверить alias и SHA-256 в том самом пользовательском файле через
keytool -list -v. Проверка другого JDK или другогоcacertsне подтверждает настройку сборки. - Проверить фактический Gradle user home, точное имя
gradle.propertiesи путь truststore. Для отделения ошибки файла настроек от ошибки сертификатов можно передать параметры явно при узком запускеhelpиз корня сервиса:
& "C:\tools\gradle\bin\gradle.bat" "-Djavax.net.ssl.trustStore=C:/Users/developer/.gradle/custom-cacerts" "-Djavax.net.ssl.trustStorePassword=changeit" help --no-daemonhelp конфигурирует сборку и может компилировать buildSrc и скачивать зависимости; это не проверка полной сборки и не запуск сервиса. Init-скрипты и плагины всё равно выполняются при конфигурации.
- Сравнить subject, issuer, серийный номер и SHA-256 импортированного сертификата с сертификатом соединения. Браузер,
keytool -printcert -sslserverи OpenSSL могут получить разные сертификаты; конкретный сетевой путь или TLS-перехват нельзя объявлять причиной без отдельного подтверждения. Получение и сравнение цепочки. - Проверить каждый hostname из ошибки. У публичного прокси зависимостей и внутреннего Nexus могут быть разные цепочки. Исправление TLS одного сервера не подтверждает второй.
- Проверить промежуточные CA. Сервер может прислать только сертификат сайта; наличие одного корневого CA тогда не гарантирует построения цепочки. Предпочтительно исправить серверную цепочку или получить проверенный комплект CA у администратора. Если в локальное хранилище добавляются промежуточные сертификаты как
trustedCertEntry, они тоже становятся доверенными точками, что шире простой передачи недостающей части цепочки. Java PKIX Trust Anchors.
Для диагностики уже воспроизводимой ошибки можно сохранить SSL-лог в PowerShell:
& "C:\tools\gradle\bin\gradle.bat" "-Djavax.net.ssl.trustStore=C:/Users/developer/.gradle/custom-cacerts" "-Djavax.net.ssl.trustStorePassword=changeit" "-Djavax.net.debug=ssl,trustmanager" help --no-daemon *> "$env:TEMP\gradle-tls.log"
Select-String -Path "$env:TEMP\gradle-tls.log" -Pattern "trustStore|TrustStoreManager|adding as trusted|subject|issuer" -Context 2,2Не все реализации и пути загрузки выводят одинаковые строки о truststore. Пустой результат одного шаблона поиска не доказывает, что диагностика не включилась или файл не загрузился. TLS-лог может содержать внутренние имена, пути и сертификаты: перед передачей нужно выбрать и обезличить нужные фрагменты. Поддержка javax.net.debug описана в JSSE.
Ошибки, которые нужно различать
| Ошибка | Что проверять дальше |
|---|---|
| HTTP 503 при загрузке дистрибутива Gradle | Доступность источника дистрибутива; это ещё не ошибка зависимостей |
no repositories are defined | Репозитории именно проблемной сборки, включая отдельный buildSrc, и корпоративный init-скрипт |
PKIX path building failed | Хранилище, реальный сертификат соединения и полноту цепочки |
Username must not be null! | Источник credentials: переменные окружения или иная конфигурация init-скрипта; это ещё не ответ сервера о неверном пароле |
| Не найден плагин, в координатах пустая версия | Сначала загрузку BOM, задающего версии; не подставлять версии наугад |
Корпоративный init.gradle, если используется, должен соответствовать окружению и получать нужные параметры сборочного сервера. Его имя или расположение в GitLab не подтверждают правильность адресов, credentials и внешних загрузок. Стандартные места подключения описаны в Gradle Init Scripts.
Исправление прежней инструкции
16.10.2026: прежнее утверждение «потребуется выход из операционной системы» заменено перезапуском процессов, использующих truststore. Добавлены отдельное пользовательское хранилище, проверка результата записи и диагностика цепочки. Общий способ применён на Windows с JDK 21 и Gradle 8.13; после добавления недостающих промежуточных CA локальная сборка заработала. Это не проверка всех JDK, оболочек и серверных конфигураций.