temporalio/temporal · error

only one of certData or certFile properties should be specif

Error message

only one of certData or certFile properties should be specified

What it means

This error is raised in ConfigureCassandraCluster (common/persistence/nosql/nosqlplugin/cassandra/gocql/client.go:61) when Cassandra TLS is enabled and the config specifies BOTH certData (inline PEM) and certFile (file path) for the client certificate. The plugin cannot choose between the two mutually exclusive sources, so cluster configuration fails immediately at startup rather than silently picking one. A sibling check enforces the same exclusivity for keyData/keyFile.

Source

Thrown at common/persistence/nosql/nosqlplugin/cassandra/gocql/client.go:61

	if cfg.Port > 0 {
		cluster.Port = cfg.Port
	}
	if cfg.User != "" && cfg.Password != "" {
		cluster.Authenticator = gocql.PasswordAuthenticator{
			Username:              cfg.User,
			Password:              cfg.Password,
			AllowedAuthenticators: cfg.AllowedAuthenticators,
		}
	}
	if cfg.Keyspace != "" {
		cluster.Keyspace = cfg.Keyspace
	}
	if cfg.Datacenter != "" {
		cluster.HostFilter = gocql.DataCentreHostFilter(cfg.Datacenter)
	}
	if cfg.TLS != nil && cfg.TLS.Enabled {
		if cfg.TLS.CertData != "" && cfg.TLS.CertFile != "" {
			return errors.New("only one of certData or certFile properties should be specified")
		}

		if cfg.TLS.KeyData != "" && cfg.TLS.KeyFile != "" {
			return errors.New("only one of keyData or keyFile properties should be specified")
		}

		if cfg.TLS.CaData != "" && cfg.TLS.CaFile != "" {
			return errors.New("only one of caData or caFile properties should be specified")
		}

		cluster.SslOpts = &gocql.SslOptions{
			CaPath:                 cfg.TLS.CaFile,
			EnableHostVerification: cfg.TLS.EnableHostVerification,
			Config:                 auth.NewTLSConfigForServer(cfg.TLS.ServerName, cfg.TLS.EnableHostVerification),
		}

		var certBytes []byte
		var keyBytes []byte

View on GitHub (pinned to bde624efd1)

Solutions

  1. Remove one of the two: keep only certFile (path-based) or only certData (inline), not both
  2. Do the same for keyData/keyFile, which the adjacent check enforces identically
  3. Audit config layering (base YAML + env overrides + secrets injection) to find where the duplicate TLS source enters
  4. Restart the service after cleaning the config; the error only appears at cluster-configuration time

Example fix

// before (config YAML)
tls:
  enabled: true
  certFile: /etc/certs/client.pem
  certData: |
    -----BEGIN CERTIFICATE-----
    ...
// after

tls:
  enabled: true
  certFile: /etc/certs/client.pem
  keyFile: /etc/certs/client.key
Defensive patterns

Strategy: validation

Validate before calling

tlsCfg := cfg.TLS
if tlsCfg != nil && tlsCfg.Enabled {
    if tlsCfg.CertData != "" && tlsCfg.CertFile != "" {
        return errors.New("specify only one of certData or certFile")
    }
    if tlsCfg.KeyData != "" && tlsCfg.KeyFile != "" {
        return errors.New("specify only one of keyData or keyFile")
    }
}
// safe: ConfigureCassandraCluster will accept TLS config

Prevention

When it happens

Trigger: Starting a server or store with Cassandra config where persistenceDataStores.cassandra.tls.enabled=true and both tls.certData and tls.certFile are non-empty (or both keyData and keyFile, per the adjacent check).

Common situations: Merging config from a template plus environment/overrides where one source sets certData and another sets certFile; copy-pasting an example config that included both fields; secrets tooling injecting inline certs while a legacy file path remains in the YAML.

Related errors


AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01). Data as JSON: /api/errors/356d8faf9e147870. Report an issue: GitHub.