{"record":{"id":"8f1362530a195c69","repo":"thanos-io/thanos","slug":"both-server-key-and-certificate-must-be-provided","errorCode":null,"errorMessage":"both server key and certificate must be provided","messagePattern":"both server key and certificate must be provided","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/tls/options.go","lineNumber":39,"sourceCode":"\n// AllowedTLSVersions is for global lists the TLS versions allowed to be used.\nvar AllowedTLSVersions = []string{\"1.0\", \"1.1\", \"1.2\", \"1.3\"}\n\n// NewServerConfig provides new server TLS configuration.\nfunc NewServerConfig(logger log.Logger, certPath, keyPath, clientCA, tlsMinVersion string, ciphers []string, curves []string) (*tls.Config, error) {\n\tif keyPath == \"\" && certPath == \"\" {\n\t\tif clientCA != \"\" {\n\t\t\treturn nil, errors.New(\"when a client CA is used a server key and certificate must also be provided\")\n\t\t}\n\n\t\tlevel.Info(logger).Log(\"msg\", \"disabled TLS, key and cert must be set to enable\")\n\t\treturn nil, nil\n\t}\n\n\tlevel.Info(logger).Log(\"msg\", \"enabling server side TLS\")\n\n\tif keyPath == \"\" || certPath == \"\" {\n\t\treturn nil, errors.New(\"both server key and certificate must be provided\")\n\t}\n\n\tminTlsVersion, err := GetTlsVersion(tlsMinVersion)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\ttlsCfg := &tls.Config{\n\t\tMinVersion: minTlsVersion,\n\t}\n\n\tcipherSuiteIDs, err := getCipherSuiteIDs(ciphers)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ttlsCfg.CipherSuites = cipherSuiteIDs\n\n\tcurveIDs, err := getCurveIDs(curves)","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/tls/options.go#L21-L57","documentation":"NewServerConfig throws this when exactly one of the server key or certificate path is provided. TLS requires both a certificate and its matching private key; providing only one is an incomplete server TLS configuration.","triggerScenarios":"A run* command is started with only --cert or only --key set (the other empty), after passing the both-empty early-return check.","commonSituations":"One of two secret-mounted file paths misconfigured in Kubernetes; typo in one flag; secret volume mounted but one path templated wrong; half-updated config after cert rotation.","solutions":["Provide both --cert and --key pointing to a matching PEM keypair","Check secret/volume mounts so both files exist at the given paths","Verify the cert and key pair match (compare modulus/public keys with openssl)","Fix templating so cert and key paths are always set together"],"exampleFix":"// before\n--cert=server.crt\n// after\n--cert=server.crt --key=server.key","handlingStrategy":"validation","validationCode":"// Pre-start check\nif (certPath == \"\") != (keyPath == \"\") {\n    return errors.New(\"--cert and --key must be provided together\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set cert and key flags from the same config object/secret","Verify both files exist in the container before launch","Avoid hand-editing one path of the pair during rotation"],"tags":["tls","configuration","server","certificates"],"backgroundTag":"missing-required-config-field","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}