{"record":{"id":"b5987be7dc9b3f78","repo":"temporalio/temporal","slug":"only-one-of-certdata-or-certfile-properties-should-b5987b","errorCode":null,"errorMessage":"only one of certData or certFile properties should be specified","messagePattern":"only one of certData or certFile properties should be specified","errorType":"validation","errorClass":"ErrTLSConfig","httpStatus":null,"severity":"error","filePath":"common/auth/tls_config_helper.go","lineNumber":121,"sourceCode":"\tif caCertPool != nil {\n\t\ttlsConfig.RootCAs = caCertPool\n\t}\n\n\t// Load client cert\n\tclientCert, err := parseClientCert(temporalTls)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif clientCert != nil {\n\t\ttlsConfig.Certificates = []tls.Certificate{*clientCert}\n\t}\n\n\treturn tlsConfig, nil\n}\n\nfunc validateTemporalTls(temporalTls *TLS) error {\n\tif temporalTls.CertData != \"\" && temporalTls.CertFile != \"\" {\n\t\treturn fmt.Errorf(\"%w: %s\", ErrTLSConfig, \"only one of certData or certFile properties should be specified\")\n\t}\n\n\tif temporalTls.KeyData != \"\" && temporalTls.KeyFile != \"\" {\n\t\treturn fmt.Errorf(\"%w: %s\", ErrTLSConfig, \"only one of keyData or keyFile properties should be specified\")\n\t}\n\n\tcertProvided := temporalTls.CertData != \"\" || temporalTls.CertFile != \"\"\n\tkeyProvided := temporalTls.KeyData != \"\" || temporalTls.KeyFile != \"\"\n\tif certProvided != keyProvided {\n\t\treturn fmt.Errorf(\"%w: %s\", ErrTLSConfig, \"cert or key is missing\")\n\t}\n\n\tif temporalTls.CaData != \"\" && temporalTls.CaFile != \"\" {\n\t\treturn fmt.Errorf(\"%w: %s\", ErrTLSConfig, \"only one of caData or caFile properties should be specified\")\n\t}\n\treturn nil\n}\n","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/auth/tls_config_helper.go#L103-L139","documentation":"This error is returned by validateTemporalTls in the Temporal TLS config helper when a TLS block specifies the certificate both inline (CertData) and via a file path (CertFile). The library requires exactly one source for the certificate so it can unambiguously load it, and it wraps the failure with ErrTLSConfig so callers can detect TLS misconfiguration.","triggerScenarios":"Calling NewTLSConfig with a *TLS struct where both CertData != \"\" and CertFile != \"\". This happens with hand-written YAML/JSON config where a cert was set inline and later a file path was added, or when config layers (defaults + overrides + env) merge both fields.","commonSituations":"Merging base config files with per-environment overrides so both certData and certFile end up populated; templating mistakes that render both fields; copying an example config and filling in both fields; Kubernetes secrets mounted as files while an older inline value remains in a ConfigMap.","solutions":["Remove one of the two fields: keep certFile if the cert is on disk, or certData (base64 of the PEM) if inline.","Inspect how config is merged/templated to find where the second value is injected, and unset it.","Validate your TLS config before startup (e.g. call validateTemporalTls or replicate its checks in config tests)."],"exampleFix":"// before\ntls:\n  certData: \"LS0tLS1CRUdJTi...\"\n  certFile: \"/etc/temporal/certs/client.pem\"\n// after\ntls:\n  certFile: \"/etc/temporal/certs/client.pem\"","handlingStrategy":"validation","validationCode":"func validateTLSOneCertSource(t *auth.TLS) error {\n\tif t.CertData != \"\" && t.CertFile != \"\" {\n\t\treturn fmt.Errorf(\"set only one of certData or certFile\")\n\t}\n\treturn nil\n}","typeGuard":"func hasExactlyOne(a, b string) bool { return (a != \"\") != (b != \"\") }","tryCatchPattern":null,"preventionTips":["Keep each cert in exactly one place: file on disk OR inline base64, per environment","Add a unit test that unmarshals your config and asserts no TLS field sets both *Data and *File","When merging config layers, explicitly null out the superseded field in overrides"],"tags":["tls","config","validation"],"backgroundTag":"tls-config-conflict","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}