{"record":{"id":"31c9ebfa00081e45","repo":"go-task/task","slug":"both-cert-and-cert-key-must-be-provided-togeth","errorCode":null,"errorMessage":"both --cert and --cert-key must be provided together","messagePattern":"both --cert and --cert-key must be provided together","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"taskfile/node_http.go","lineNumber":32,"sourceCode":"\n\t\"github.com/go-task/task/v3/errors\"\n\t\"github.com/go-task/task/v3/internal/execext\"\n\t\"github.com/go-task/task/v3/internal/filepathext\"\n)\n\n// An HTTPNode is a node that reads a Taskfile from a remote location via HTTP.\ntype HTTPNode struct {\n\t*baseNode\n\turl    *url.URL     // stores url pointing actual remote file. (e.g. with Taskfile.yml)\n\tclient *http.Client // HTTP client with optional TLS configuration\n}\n\n// buildHTTPClient creates an HTTP client with optional TLS configuration.\n// If no certificate options are provided, it returns http.DefaultClient.\nfunc buildHTTPClient(insecure bool, caCert, cert, certKey string) (*http.Client, error) {\n\t// Validate that cert and certKey are provided together\n\tif (cert != \"\" && certKey == \"\") || (cert == \"\" && certKey != \"\") {\n\t\treturn nil, fmt.Errorf(\"both --cert and --cert-key must be provided together\")\n\t}\n\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()","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/go-task/task/blob/385e5ad92af02877b6d7cf9dcc963b5ed916e70a/taskfile/node_http.go#L14-L50","documentation":"buildHTTPClient enforces that a TLS client certificate (--cert) and its key (--cert-key) are supplied as a pair. Providing exactly one of them is invalid because Go's tls.Config requires both to load a client certificate, so it errors before any HTTP request is made.","triggerScenarios":"NewHTTPNode -> buildHTTPClient called with cert set and certKey empty, or certKey set and cert empty — e.g. invoking task with --cert but forgetting --cert-key (or vice versa) when fetching a remote Taskfile over HTTPS.","commonSituations":"Mutual-TLS setups where a user passes the client cert but forgets the key path; flags wired from config where only one of the two values was populated; copy-pasting examples that set only one flag.","solutions":["Pass both flags together: --cert client.crt --cert-key client.key","If you don't need client certs, remove both flags entirely","Check the config file/env that feeds these flags to ensure both values are set","Regenerate or locate the missing key matching the certificate"],"exampleFix":"# before\ntask --cert ./client.crt -f https://example.com/Taskfile.yml\n# after\ntask --cert ./client.crt --cert-key ./client.key -f https://example.com/Taskfile.yml","handlingStrategy":"validation","validationCode":"if (cert == \"\") != (certKey == \"\") {\n    return fmt.Errorf(\"--cert and --cert-key must be provided together\")\n}","typeGuard":"func hasCompleteClientCertPair(cert, certKey string) bool {\n    return (cert == \"\") == (certKey == \"\")\n}","tryCatchPattern":"node, err := taskfile.NewHTTPNode(..., cert, certKey, ...)\nif err != nil {\n    if strings.Contains(err.Error(), \"must be provided together\") {\n        // surface flag guidance to the user or fall back to default client\n    }\n    return err\n}","preventionTips":["Always pass --cert and --cert-key as a pair in scripts/wrappers","Store both paths together in your task runner config","Add a pre-flight check in wrapper scripts before invoking task","Omit both flags when mTLS is not required"],"tags":["http","tls","mtls","cli-flags","validation"],"backgroundTag":"tls-cert-key-mismatch","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"}