temporalio/temporal · error

only one of keyData or keyFile properties should be specifie

Error message

only one of keyData or keyFile properties should be specified

What it means

ConfigureCassandraCluster validates the TLS block of the Cassandra config before building a gocql cluster config. It rejects configs where both inline cert content (KeyData) and a file path (KeyFile) are provided for the client private key, since the loader cannot decide which source to use. This is a fail-fast config sanity check.

Source

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

		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
		var err error

		if cfg.TLS.CertFile != "" {
			certBytes, err = os.ReadFile(cfg.TLS.CertFile)

View on GitHub (pinned to bde624efd1)

Solutions

  1. Remove either the keyData or the keyFile property from the cassandra TLS config, keeping only one
  2. If using file-based secrets (common in k8s), set keyFile and clear keyData to ""
  3. If injecting the key inline (e.g. base64 in dynamic config), set keyData and remove keyFile

Example fix

// before
persistence:
  cassandra:
    tls:
      enabled: true
      keyFile: /etc/certs/key.pem
      keyData: LS0tLS1CRUdJTi...
// after
persistence:
  cassandra:
    tls:
      enabled: true
      keyFile: /etc/certs/key.pem
Defensive patterns

Strategy: validation

Validate before calling

func validateTLSKey(tls config.TLS) error {
    if !tls.Enabled { return nil }
    if tls.KeyData != "" && tls.KeyFile != "" {
        return errors.New("specify only one of keyData or keyFile")
    }
    return nil
}

Prevention

When it happens

Trigger: Calling NewCassandraCluster (via ConfigureCassandraCluster) with persistence config where cfg.TLS.Enabled is true and both cfg.TLS.KeyData and cfg.TLS.KeyFile are non-empty strings.

Common situations: Environment templating that injects both a base64 key and a mounted secret file path; copying an example config and filling in both fields; k8s operators setting KeyData while a sidecar already set KeyFile.

Related errors


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