temporalio/temporal · error
cannot specify CertFile and CertData at the same time
Error message
cannot specify CertFile and CertData at the same time
What it means
validateWorkerTLS enforces that WorkerTLS config specifies a certificate either by file path (CertFile) or inline data (CertData), never both. Supplying both is ambiguous, so validation fails with this error before any TLS config is built. It is checked when validateRootTLS validates worker TLS settings.
Source
Thrown at common/rpc/encryption/tls_factory.go:109
}
if err := validateClientTLS(&cfg.Client); err != nil {
return err
}
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 {View on GitHub (pinned to bde624efd1)
Solutions
- Remove one of the two: keep CertFile for on-disk certs or CertData for inline PEM, not both.
- If both come from merged dynamic config layers, delete the obsolete field from the higher-precedence layer.
- After fixing, ensure KeyFile/KeyData follow the same single-source rule.
Example fix
// before certFile: /etc/certs/client.pem certData: | -----BEGIN CERTIFICATE-----... // after certFile: /etc/certs/client.pem # certData removed
Defensive patterns
Strategy: validation
Validate before calling
if cfg.CertFile != "" && cfg.CertData != "" {
return errors.New("worker TLS cert: set only one of CertFile/CertData")
} Try / catch
if err := validateWorkerTLS(&cfg.Global.WorkerTLS); err != nil {
return fmt.Errorf("worker TLS config invalid: %w", err)
} Prevention
- Standardize on one cert source (files or inline data) per environment.
- Audit stacked dynamic config layers for duplicate fields.
- Run validation in CI before shipping config.
When it happens
Trigger: WorkerTLS block where both cfg.CertFile and cfg.CertData are non-empty — e.g. migrating from file-based to inline secrets while keeping the old path, or merging dynamic config layers that each set a different field.
Common situations: Setting certDataFile contents via secret injection while a legacy certFile line remains in the config; stacking multiple dynamic config YAMLs where one sets CertFile and another CertData.
Related errors
- cannot specify KeyFile and KeyData 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/28cfaed2c6aa69cd.
Report an issue: GitHub.