{"record":{"id":"4014db7f7688a23c","repo":"benbjohnson/litestream","slug":"client-cert-and-client-key-must-both-be-specified","errorCode":null,"errorMessage":"client-cert and client-key must both be specified for mutual TLS authentication","messagePattern":"client-cert and client-key must both be specified for mutual TLS authentication","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/litestream/main.go","lineNumber":1949,"sourceCode":"\t\tif bucketPath != \"\" {\n\t\t\tbucket = strings.Trim(bucketPath, \"/\")\n\t\t}\n\t}\n\n\t// Use bucket from config if not extracted from URL\n\tif bucket == \"\" {\n\t\tbucket = c.Bucket\n\t}\n\n\t// Ensure required settings are set\n\tif bucket == \"\" {\n\t\treturn nil, fmt.Errorf(\"bucket required for NATS replica\")\n\t}\n\n\t// Validate TLS configuration\n\t// Both client cert and key must be specified together\n\tif (c.ClientCert != \"\") != (c.ClientKey != \"\") {\n\t\treturn nil, fmt.Errorf(\"client-cert and client-key must both be specified for mutual TLS authentication\")\n\t}\n\n\t// Build replica client\n\tclient := nats.NewReplicaClient()\n\tclient.URL = url\n\tclient.BucketName = bucket\n\n\t// Set authentication options\n\tclient.JWT = c.JWT\n\tclient.Seed = c.Seed\n\tclient.Creds = c.Creds\n\tclient.NKey = c.NKey\n\tclient.Username = c.Username\n\tclient.Password = c.Password\n\tclient.Token = c.Token\n\n\t// Set TLS options\n\tif c.TLS != nil {","sourceCodeStart":1931,"sourceCodeEnd":1967,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/cmd/litestream/main.go#L1931-L1967","documentation":"NATS mutual TLS requires both a client certificate and its corresponding private key. newReplicaClientFromConfig rejects any configuration that specifies exactly one of `client-cert` / `client-key`, since a lone cert or key cannot form a valid TLS client identity.","triggerScenarios":"Setting `client-cert: /path/cert.pem` without `client-key` (or vice versa) in a NATS replica config.","commonSituations":"Following mTLS docs that mention only the cert; key stored separately and forgotten; typo like `client_key` so one half silently parses as empty.","solutions":["Set both `client-cert` and `client-key` to their PEM file paths.","If mutual TLS is not required, remove the single orphan field entirely.","Check field spelling/casing so both values are actually parsed."],"exampleFix":"# before\nreplicas:\n  - url: nats://nats.example.com\n    client-cert: /etc/litestream/client.pem\n# after\nreplicas:\n  - url: nats://nats.example.com\n    client-cert: /etc/litestream/client.pem\n    client-key: /etc/litestream/client-key.pem","handlingStrategy":"validation","validationCode":"// Ensure mTLS fields come as a pair before building config\nif (cfg.ClientCert != \"\") != (cfg.ClientKey != \"\") {\n    return fmt.Errorf(\"client-cert and client-key must be set together\")\n}","typeGuard":null,"tryCatchPattern":"if err := runReplicate(); err != nil {\n    if strings.Contains(err.Error(), \"client-cert and client-key\") {\n        // fix config to include both files\n    }\n}","preventionTips":["Treat client-cert/client-key as one required pair in your config templates.","Verify both PEM files exist and are readable before starting litestream."],"tags":["nats","tls","mutual-tls","config"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}