zitadel/zitadel · error

TLS is enabled: please specify a key (path) and a cert (path

Error message

TLS is enabled: please specify a key (path) and a cert (path) or disable TLS if needed (e.g. by setting flag `--tlsMode external` or `--tlsMode disabled

What it means

ErrMissingConfig in internal/config/network/config.go is returned when TLS is enabled but the TLS config lacks a server key or certificate. ZITADEL refuses to start serving with incomplete TLS material and instructs the operator to provide key/cert or switch the TLS mode. It is a startup configuration error.

Source

Thrown at internal/config/network/config.go:10

package network

import (
	"crypto/tls"
	"errors"
	"os"
)

var (
	ErrMissingConfig = errors.New("TLS is enabled: please specify a key (path) and a cert (path) or disable TLS if needed (e.g. by setting flag `--tlsMode external` or `--tlsMode disabled")
)

type TLS struct {
	//If enabled, ZITADEL will serve all traffic over TLS (HTTPS and gRPC)
	//you must then also provide a private key and certificate to be used for the connection
	//either directly or by a path to the corresponding file
	Enabled bool
	//Path to the private key of the TLS certificate, it will be loaded into the Key
	//and overwrite any exising value
	KeyPath string
	//Path to the certificate for the TLS connection, it will be loaded into the Cert
	//and overwrite any exising value
	CertPath string
	//Private key of the TLS certificate (KeyPath will this overwrite, if specified)
	Key []byte
	//Certificate for the TLS connection (CertPath will this overwrite, if specified)
	Cert []byte
}

View on GitHub (pinned to 13948f2bcd)

Solutions

  1. Provide the private key and certificate, either inline in the tls config or via key/cert path options
  2. If a proxy (e.g. nginx/traefik) terminates TLS, start ZITADEL with --tlsMode external
  3. For purely local/dev setups, disable TLS with --tlsMode disabled
  4. Verify configured cert/key paths exist and load successfully so Cert/Key are populated

Example fix

# before
TLS:
  Enabled: true
# after
TLS:
  Enabled: true
  KeyPath: /etc/zitadel/tls/key.pem
  CertPath: /etc/zitadel/tls/cert.pem
# or run with: --tlsMode external (proxy terminates TLS)
Defensive patterns

Strategy: validation

Validate before calling

if tlsCfg.Enabled && (tlsCfg.Key == nil || tlsCfg.Cert == nil) {
    return errors.New("TLS enabled but key/cert missing: set keyPath/certPath or use --tlsMode external|disabled")
}

Try / catch

// startup config is not catchable at runtime; validate before boot
if err := validateTLSConfig(cfg.TLS); err != nil {
    log.Fatalf("invalid TLS configuration: %v", err)
}

Prevention

When it happens

Trigger: TLS enabled (default tlsMode) while tls.Key or tls.Cert are nil in the compiled Config — i.e. no key/cert given inline and no KeyPath/CertPath resolvable, via Config() at internal/config/network/config.go:47.

Common situations: Operator enables TLS but forgets to set the key/cert files in config.yaml or env vars; a path typo makes the file load fail leaving Cert/Key nil; running locally behind a reverse proxy while TLS stays enabled instead of --tlsMode external or disabled.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of zitadel/zitadel@13948f2bcd (2026-09-06). Data as JSON: /api/errors/e8f693dd8fb616d4. Report an issue: GitHub.