{"record":{"id":"e27289ed764c3bea","repo":"apple/pkl","slug":"cannotparsecertfile","errorCode":"cannotParseCertFile","errorMessage":"cannotParseCertFile: ${source}: ${reason}","messagePattern":"cannotParseCertFile: (.+?): (.+?)","errorType":"exception","errorClass":"HttpClientException","httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/http/JdkHttpClient.java","lineNumber":190,"sourceCode":"    return certificates;\n  }\n\n  private static void collectCertificates(\n      ArrayList<Certificate> anchors,\n      CertificateFactory factory,\n      InputStream stream,\n      Object source) {\n    var input = new PushbackInputStream(stream);\n\n    try {\n      var peekByte = input.read();\n      if (peekByte == -1) {\n        throw new HttpClientException(ErrorMessages.create(\"emptyCertFile\", source));\n      } else {\n        input.unread(peekByte);\n      }\n    } catch (IOException e) {\n      throw new HttpClientException(\n          ErrorMessages.create(\"cannotParseCertFile\", source, Exceptions.getRootReason(e)));\n    }\n\n    var first = true;\n    while (true) {\n      try {\n        anchors.add(factory.generateCertificate(input));\n      } catch (CertificateException e) {\n        if (e.getCause() instanceof IOException ioExc) {\n          if (Objects.equals(ioExc.getMessage(), \"Empty input\")) {\n            if (first) {\n              throw new HttpClientException(\n                  ErrorMessages.create(\"cannotParseCertFile\", source, \"No certificate data found\"));\n            }\n            break;\n          }\n          if (Objects.equals(ioExc.getMessage(), \"Duplicate extensions not allowed\")) continue;\n        }","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/http/JdkHttpClient.java#L172-L208","documentation":"Pkl could not parse the certificate source as X.509 while peeking/reading it; an IOException occurred during CertificateFactory parsing and its root reason is reported. This variant fires when the parse stream itself raises an I/O error for the given source (file path or \"<unavailable>\" for inline bytes).","triggerScenarios":"During collectCertificates, an IOException escapes the certificate parsing loop or the initial peek; the source label (file path or \"<unavailable>\") and root IO reason are interpolated. Happens with corrupted reads or streams that fail mid-parse.","commonSituations":"Partially written or truncated certificate file that fails mid-stream, unreadable blocks on a failing disk, or inline certificate bytes that wrap a broken stream.","solutions":["Read the `${reason}` in the message and address the underlying I/O problem.","Re-obtain the certificate file; replace truncated or corrupted copies.","Verify the file is a valid PEM or DER certificate using `openssl x509 -in <file> -noout`.","Ensure no other process is concurrently writing the certificate file while Pkl reads it."],"exampleFix":"// before (shell)\n$ openssl x509 -in broken-ca.pem -noout\nError: unable to load certificate\n// after (shell)\n$ curl -fsSLO https://ca.example.com/ca.pem && openssl x509 -in ca.pem -noout","handlingStrategy":"try-catch","validationCode":"try (InputStream in = Files.newInputStream(certPath)) {\n  CertificateFactory.getInstance(\"X.509\").generateCertificate(in); // fail fast\n} catch (Exception e) {\n  throw new IllegalStateException(\"Pre-validation failed: \" + e.getMessage(), e);\n}","typeGuard":null,"tryCatchPattern":"try {\n  // use the HTTP client\n} catch (HttpClientException e) {\n  if (e.getMessage().startsWith(\"cannotParseCertFile\")) {\n    // replace the certificate file and retry\n  }\n}","preventionTips":["Pre-validate certificates with `openssl x509 -noout` before deployment.","Never share a certificate file between concurrent writers and readers.","Re-download certs rather than repairing truncated files.","Keep certificate bundles in versioned, immutable artifacts."],"tags":["http","tls","parsing","io"],"backgroundTag":"invalid-argument-format","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}