temporalio/temporal · error
cannot specify KeyFile and KeyData at the same time
Error message
cannot specify KeyFile and KeyData at the same time
What it means
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.
Source
Thrown at common/rpc/encryption/tls_factory.go:112
}
for host, hostConfig := range cfg.PerHostOverrides {
if strings.TrimSpace(host) == "" {
return fmt.Errorf("host name cannot be empty string")
}
if err := validateServerTLS(&hostConfig); err != nil {
return err
}
}
return nil
}
func validateWorkerTLS(cfg *config.WorkerTLS) error {
if cfg.CertFile != "" && cfg.CertData != "" {
return fmt.Errorf("cannot specify CertFile and CertData at the same time")
}
if cfg.KeyFile != "" && cfg.KeyData != "" {
return fmt.Errorf("cannot specify KeyFile and KeyData at the same time")
}
return validateClientTLS(&cfg.Client)
}
func validateServerTLS(cfg *config.ServerTLS) error {
if cfg.CertFile != "" && cfg.CertData != "" {
return fmt.Errorf("cannot specify CertFile and CertData at the same time")
}
if cfg.KeyFile != "" && cfg.KeyData != "" {
return fmt.Errorf("cannot specify KeyFile and KeyData at the same time")
}
if err := validateCAs(cfg.ClientCAData); err != nil {
return fmt.Errorf("invalid ServerTLS.ClientCAData: %w", err)
}
if err := validateCAs(cfg.ClientCAFiles); err != nil {
return fmt.Errorf("invalid ServerTLS.ClientCAFiles: %w", err)
}
if len(cfg.ClientCAFiles) > 0 && len(cfg.ClientCAData) > 0 {View on GitHub (pinned to bde624efd1)
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.
Example fix
// before keyFile: /etc/certs/client.key keyData: | -----BEGIN PRIVATE KEY-----... // after keyData: | -----BEGIN PRIVATE KEY-----... # keyFile removed
Defensive patterns
Strategy: validation
Validate before calling
if cfg.KeyFile != "" && cfg.KeyData != "" {
return errors.New("worker TLS key: set only one of KeyFile/KeyData")
} Try / catch
if err := validateWorkerTLS(&cfg.Global.WorkerTLS); err != nil {
return fmt.Errorf("worker TLS config invalid: %w", err)
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- cannot specify CertFile and CertData at the same time
- only one of certData or certFile properties should be specif
- only one of keyData or keyFile properties should be specifie
- cert or key is missing
- only one of caData or caFile properties should be specified
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/8ec8b1856719656c.
Report an issue: GitHub.