{"record":{"id":"821348300e1ee2db","repo":"go-task/task","slug":"failed-to-load-client-certificate-w","errorCode":null,"errorMessage":"failed to load client certificate: %w","messagePattern":"failed to load client certificate: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"taskfile/node_http.go","lineNumber":61,"sourceCode":"\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\n}\n\nfunc NewHTTPNode(\n\tentrypoint string,\n\tdir string,\n\tinsecure bool,\n\topts ...NodeOption,\n) (*HTTPNode, error) {\n\tbase := NewBaseNode(dir, opts...)","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/go-task/task/blob/385e5ad92af02877b6d7cf9dcc963b5ed916e70a/taskfile/node_http.go#L43-L79","documentation":"This error wraps a tls.LoadX509KeyPair failure inside buildHTTPClient in taskfile/node_http.go. The library throws it when a client certificate/key pair was configured for the HTTP node but the files could not be read or parsed as a valid PEM key pair. The underlying TLS error is preserved via %w so you can see whether the problem was file access or certificate/key content.","triggerScenarios":"Calling NewHTTPNode (or buildHTTPClient via tests) with both a cert and certKey path set where the files do not exist, are unreadable (permissions), are empty, are in the wrong format (e.g. DER instead of PEM), or the key does not match the certificate.","commonSituations":"Misconfigured taskfile remote-fetch TLS settings: typo in cert/key path, relative path resolved against wrong working directory, certificate rotated and old files deleted, base64-encoded PEM not decoded to disk, or key regenerated without updating the cert.","solutions":["Verify both cert and certKey files exist at the exact paths passed and are readable by the process (ls -l / absolute paths).","Open both files and confirm they contain PEM blocks (-----BEGIN CERTIFICATE----- / -----BEGIN ... PRIVATE KEY-----); convert DER with `openssl x509 -inform der` / `openssl rsa -inform der` if needed.","Confirm the key matches the cert: `openssl x509 -noout -modulus -in cert.pem` vs `openssl rsa -noout -modulus -in key.pem` should be equal.","If you do not need mutual TLS, pass empty cert/certKey strings so the branch is skipped entirely."],"exampleFix":"// before (paths wrong / files missing)\nNewHTTPNode(\"https://example.com/taskfile.yml\", cert: \"certs/client.crt\", certKey: \"certs/client.key\")\n// after (absolute, verified paths)\nNewHTTPNode(\"https://example.com/taskfile.yml\", cert: \"/etc/task/certs/client.crt\", certKey: \"/etc/task/certs/client.key\")","handlingStrategy":"validation","validationCode":"for _, p := range []string{certPath, keyPath} {\n    if p == \"\" { continue }\n    fi, err := os.Stat(p)\n    if err != nil { return fmt.Errorf(\"missing TLS file %s: %w\", p, err) }\n    if fi.Size() == 0 { return fmt.Errorf(\"empty TLS file %s\", p) }\n    if _, err := tls.LoadX509KeyPair(certPath, keyPath); err != nil {\n        return fmt.Errorf(\"invalid key pair: %w\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use absolute paths for cert/key in taskfiles and configs.","Run `openssl verify` and modulus comparison on cert/key after every rotation.","Add a startup preflight that dry-runs tls.LoadX509KeyPair.","Never commit or move cert/key without updating the configured paths."],"tags":["tls","certificate","http-client","config"],"backgroundTag":"tls-certificate-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"}