{"record":{"id":"11d5e31c8b041948","repo":"go-task/task","slug":"failed-to-parse-ca-certificate","errorCode":null,"errorMessage":"failed to parse CA certificate","messagePattern":"failed to parse CA certificate","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"taskfile/node_http.go","lineNumber":52,"sourceCode":"\n\t// If no TLS customization is needed, return the default client\n\tif !insecure && caCert == \"\" && cert == \"\" {\n\t\treturn http.DefaultClient, nil\n\t}\n\n\ttlsConfig := &tls.Config{\n\t\tInsecureSkipVerify: insecure, //nolint:gosec\n\t}\n\n\t// Load custom CA certificate if provided\n\tif caCert != \"\" {\n\t\tcaCertData, err := os.ReadFile(caCert)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to read CA certificate: %w\", err)\n\t\t}\n\t\tcaCertPool := x509.NewCertPool()\n\t\tif !caCertPool.AppendCertsFromPEM(caCertData) {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse CA certificate\")\n\t\t}\n\t\ttlsConfig.RootCAs = caCertPool\n\t}\n\n\t// Load client certificate and key if provided\n\tif cert != \"\" && certKey != \"\" {\n\t\tclientCert, err := tls.LoadX509KeyPair(cert, certKey)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to load client certificate: %w\", err)\n\t\t}\n\t\ttlsConfig.Certificates = []tls.Certificate{clientCert}\n\t}\n\n\treturn &http.Client{\n\t\tTransport: &http.Transport{\n\t\t\tTLSClientConfig: tlsConfig,\n\t\t},\n\t}, nil","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/go-task/task/blob/385e5ad92af02877b6d7cf9dcc963b5ed916e70a/taskfile/node_http.go#L34-L70","documentation":"After reading the CA file, buildHTTPClient calls x509.AppendCertsFromPEM; if no certificates could be parsed from the data, the pool is empty and this error is returned. It means the file exists and is readable but contains no valid PEM certificates.","triggerScenarios":"NewHTTPNode -> buildHTTPClient: caCert file read succeeds but AppendCertsFromPEM returns false — e.g. the file holds DER-encoded certs, a private key, HTML/error text, or an empty file.","commonSituations":"Downloading a CA over a captive portal that returns an HTML error page saved as the cert; exporting certs in DER instead of PEM format; pointing --cacert at a key file or a combined file whose cert block is malformed; truncated downloads.","solutions":["Convert the certificate to PEM format: openssl x509 -inform DER -in ca.der -out ca.pem","Open the file and verify it contains a -----BEGIN CERTIFICATE----- block","Re-download/export the CA bundle (the file may be an HTML error page or truncated)","Ensure you are pointing at the CA certificate, not a private key or CSR"],"exampleFix":"# before (DER export)\ntask --cacert ./corp-ca.cer ...\n# after (PEM conversion)\nopenssl x509 -inform DER -in corp-ca.cer -out corp-ca.pem\ntask --cacert ./corp-ca.pem ...","handlingStrategy":"validation","validationCode":"pemBytes, err := os.ReadFile(caPath)\nif err != nil {\n    return err\n}\nif !x509.NewCertPool().AppendCertsFromPEM(pemBytes) {\n    return fmt.Errorf(\"%s contains no valid PEM certificates\", caPath)\n}","typeGuard":"func isValidPEMCert(path string) bool {\n    b, err := os.ReadFile(path)\n    if err != nil {\n        return false\n    }\n    return x509.NewCertPool().AppendCertsFromPEM(b)\n}","tryCatchPattern":"node, err := taskfile.NewHTTPNode(..., caCert, ...)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to parse CA certificate\") {\n        // convert to PEM or re-download the bundle, then retry\n    }\n    return err\n}","preventionTips":["Ensure CA files are PEM-encoded (BEGIN CERTIFICATE blocks), not DER","Validate the bundle with `openssl x509 -in ca.pem -noout -text` before use","Never point --cacert at private keys, CSRs, or HTML error pages","Verify downloaded bundles aren't truncated (check size/checksum)"],"tags":["http","tls","ca-cert","pem","certificates"],"backgroundTag":"ca-cert-load-failed","analyzedSha":"385e5ad92af02877b6d7cf9dcc963b5ed916e70a","analyzedAt":"2026-09-05T09:01:05.226Z","contentChangedAt":"2026-09-05T09:01:05.226Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}