{"record":{"id":"e9a5c00406bce404","repo":"apple/pkl","slug":"could-not-find-bundled-certificates","errorCode":null,"errorMessage":"Could not find bundled certificates","messagePattern":"Could not find bundled certificates","errorType":"exception","errorClass":"CliException","httpStatus":null,"severity":"error","filePath":"pkl-commons-cli/src/main/kotlin/org/pkl/commons/cli/CliCommand.kt","lineNumber":237,"sourceCode":"  private fun HttpClient.Builder.addDefaultCliCertificates() {\n    val caCertsDir = IoUtils.getSystemCaCertsDir()\n    var certsAdded = false\n    if (Files.isDirectory(caCertsDir)) {\n      Files.list(caCertsDir)\n        .filter { it.isRegularFile() && !it.fileName.toString().startsWith(\".\") }\n        .forEach { cert ->\n          certsAdded = true\n          addCertificates(cert)\n        }\n    }\n    if (certsAdded) {\n      DebugLogger.log(\"Loading CA certificates from ${caCertsDir.normalize().absolutePathString()}\")\n    } else {\n      DebugLogger.log(\"Using built-in CA certificates\")\n      val defaultCerts =\n        this@CliCommand.javaClass.classLoader.getResourceAsStream(\n          \"org/pkl/commons/cli/PklCARoots.pem\"\n        ) ?: throw CliException(\"Could not find bundled certificates\")\n      addCertificates(defaultCerts.readAllBytes())\n    }\n  }\n\n  /**\n   * The HTTP client used for this command.\n   *\n   * To release resources held by the HTTP client in a timely manner, call [HttpClient.close].\n   */\n  val httpClient: HttpClient by lazy {\n    with(HttpClient.builder()) {\n      setTestPort(cliOptions.testPort)\n      if (cliOptions.normalizedCaCertificates.isEmpty()) {\n        addDefaultCliCertificates()\n      } else {\n        for (file in cliOptions.normalizedCaCertificates) addCertificates(file)\n      }\n      if ((proxyAddress ?: noProxy) != null) {","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-commons-cli/src/main/kotlin/org/pkl/commons/cli/CliCommand.kt#L219-L255","documentation":"CliCommand falls back to a CA root certificate bundle (PklCARoots.pem) embedded as a classpath resource when no CA certs directory is configured. This error means the bundle resource could not be found on the classpath, so TLS trust cannot be set up. It indicates a broken/trimmed build artifact or an unusual classloader that cannot see the resource.","triggerScenarios":"Running a CLI command that needs an HTTP client when (1) no CA certificates directory is set, and (2) classLoader.getResourceAsStream(\"org/pkl/commons/cli/PklCARoots.pem\") returns null — e.g. the pem was stripped from the jar, a shaded/proguarded build excluded resources, or a custom classloader is in use.","commonSituations":"Deploying a repackaged jar that omitted resource files; running tests with a filtered classpath; using a module system or fat-jar plugin that excludes .pem resources; corporate environment where devs expected to point at a custom CA dir but left it unset on a broken distribution.","solutions":["Verify org/pkl/commons/cli/PklCARoots.pem exists inside the jar: unzip -l app.jar | grep PklCARoots; if missing, rebuild or re-download the distribution unmodified.","Provide CA certificates explicitly so the fallback is never used: set the CA certs directory option (e.g. --ca-certificates or PKL_CA_CERTIFICATES_DIR) to a directory of PEM files.","If using shading/proguard, add a keep/include rule for org/pkl/commons/cli/*.pem resources.","Check for a custom classloader that cannot see the resource; run with the standard classloader."],"exampleFix":"// before\njava -jar pkl.jar eval // fails on stripped jar\n// after\nexport PKL_CA_CERTIFICATES_DIR=/etc/ssl/certs\njava -jar pkl.jar eval","handlingStrategy":"fallback","validationCode":"val pem = CliCommand::class.java.classLoader.getResourceAsStream(\"org/pkl/commons/cli/PklCARoots.pem\")\nrequireNotNull(pem) { \"bundled PklCARoots.pem missing from classpath; set CA certs dir instead\" }","typeGuard":"fun hasBundledCerts(): Boolean =\n  CliCommand::class.java.classLoader.getResource(\"org/pkl/commons/cli/PklCARoots.pem\") != null","tryCatchPattern":"try {\n  runCommand()\n} catch (e: CliException) {\n  if (e.message?.contains(\"bundled certificates\") == true) {\n    // rebuild distribution or set CA certs directory and retry\n  } else throw e\n}","preventionTips":["Always ship the original, unmodified jar/distribution; do not strip .pem resources when shading.","In restricted network environments, configure the CA certificates directory explicitly instead of relying on the bundle.","Smoke-test CLI commands that make HTTPS calls in CI to catch broken artifacts early."],"tags":["tls","certificates","classpath","cli"],"backgroundTag":"resource-not-found","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}