{"record":{"id":"8ec8b1856719656c","repo":"temporalio/temporal","slug":"cannot-specify-keyfile-and-keydata-at-the-same-tim","errorCode":null,"errorMessage":"cannot specify KeyFile and KeyData at the same time","messagePattern":"cannot specify KeyFile and KeyData at the same time","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/rpc/encryption/tls_factory.go","lineNumber":112,"sourceCode":"\t}\n\tfor host, hostConfig := range cfg.PerHostOverrides {\n\n\t\tif strings.TrimSpace(host) == \"\" {\n\t\t\treturn fmt.Errorf(\"host name cannot be empty string\")\n\t\t}\n\t\tif err := validateServerTLS(&hostConfig); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc validateWorkerTLS(cfg *config.WorkerTLS) error {\n\tif cfg.CertFile != \"\" && cfg.CertData != \"\" {\n\t\treturn fmt.Errorf(\"cannot specify CertFile and CertData at the same time\")\n\t}\n\tif cfg.KeyFile != \"\" && cfg.KeyData != \"\" {\n\t\treturn fmt.Errorf(\"cannot specify KeyFile and KeyData at the same time\")\n\t}\n\treturn validateClientTLS(&cfg.Client)\n}\n\nfunc validateServerTLS(cfg *config.ServerTLS) error {\n\tif cfg.CertFile != \"\" && cfg.CertData != \"\" {\n\t\treturn fmt.Errorf(\"cannot specify CertFile and CertData at the same time\")\n\t}\n\tif cfg.KeyFile != \"\" && cfg.KeyData != \"\" {\n\t\treturn fmt.Errorf(\"cannot specify KeyFile and KeyData at the same time\")\n\t}\n\tif err := validateCAs(cfg.ClientCAData); err != nil {\n\t\treturn fmt.Errorf(\"invalid ServerTLS.ClientCAData: %w\", err)\n\t}\n\tif err := validateCAs(cfg.ClientCAFiles); err != nil {\n\t\treturn fmt.Errorf(\"invalid ServerTLS.ClientCAFiles: %w\", err)\n\t}\n\tif len(cfg.ClientCAFiles) > 0 && len(cfg.ClientCAData) > 0 {","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/rpc/encryption/tls_factory.go#L94-L130","documentation":"Same mutual-exclusion rule as the cert: validateWorkerTLS rejects WorkerTLS configs that specify both KeyFile (key on disk) and KeyData (inline key PEM). The private key must have exactly one source to avoid ambiguity. Checked during root TLS validation before any client config is created.","triggerScenarios":"WorkerTLS block where cfg.KeyFile and cfg.KeyData are both non-empty — duplicated key configuration across config layers or a partial migration from file to inline secrets.","commonSituations":"Secrets tooling injecting keyData while the old keyFile remains; copying an example config that used inline data onto an environment that already uses file paths.","solutions":["Keep exactly one of KeyFile or KeyData; remove the other.","Audit merged dynamic config layers for duplicate key settings.","If inline data is preferred for containers, delete the stale file path entry."],"exampleFix":"// before\nkeyFile: /etc/certs/client.key\nkeyData: |\n  -----BEGIN PRIVATE KEY-----...\n// after\nkeyData: |\n  -----BEGIN PRIVATE KEY-----...   # keyFile removed","handlingStrategy":"validation","validationCode":"if cfg.KeyFile != \"\" && cfg.KeyData != \"\" {\n    return errors.New(\"worker TLS key: set only one of KeyFile/KeyData\")\n}","typeGuard":null,"tryCatchPattern":"if err := validateWorkerTLS(&cfg.Global.WorkerTLS); err != nil {\n    return fmt.Errorf(\"worker TLS config invalid: %w\", err)\n}","preventionTips":["Never commit both inline and file-based key references in the same block.","When migrating to injected secrets, delete legacy file paths in the same change.","Validate merged config output, not just individual layers."],"tags":["config","validation","tls","worker","private-key"],"backgroundTag":"tls-config-validation-failed","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}