go-sql-driver/mysql · error

invalid value / unknown config name: {cfg.TLSConfig}

Error message

invalid value / unknown config name: {cfg.TLSConfig}

What it means

normalize() resolves cfg.TLSConfig against the reserved words 'false'/'', 'true', 'skip-verify', 'preferred', then falls back to the registry populated by RegisterTLSConfig. If the key is not reserved and not registered, getTLSConfigClone returns nil and the driver returns 'invalid value / unknown config name' at dsn.go:210.

Source

Thrown at dsn.go:210

	} else if cfg.Net == "tcp" {
		cfg.Addr = ensureHavePort(cfg.Addr)
	}

	if cfg.TLS == nil {
		switch cfg.TLSConfig {
		case "false", "":
			// don't set anything
		case "true":
			cfg.TLS = &tls.Config{}
		case "skip-verify":
			cfg.TLS = &tls.Config{InsecureSkipVerify: true}
		case "preferred":
			cfg.TLS = &tls.Config{InsecureSkipVerify: true}
			cfg.AllowFallbackToPlaintext = true
		default:
			cfg.TLS = getTLSConfigClone(cfg.TLSConfig)
			if cfg.TLS == nil {
				return errors.New("invalid value / unknown config name: " + cfg.TLSConfig)
			}
		}
	}

	if cfg.TLS != nil && cfg.TLS.ServerName == "" && !cfg.TLS.InsecureSkipVerify {
		host, _, err := net.SplitHostPort(cfg.Addr)
		if err == nil {
			cfg.TLS.ServerName = host
		}
	}

	if cfg.ServerPubKey != "" {
		cfg.pubKey = getServerPubKey(cfg.ServerPubKey)
		if cfg.pubKey == nil {
			return errors.New("invalid value / unknown server pub key name: " + cfg.ServerPubKey)
		}
	}

View on GitHub (pinned to c426bd9379)

Solutions

  1. Call mysql.RegisterTLSConfig('custom', &tls.Config{...}) before sql.Open/ParseDSN, in the same process.
  2. Verify the key string matches exactly (case, spelling) between RegisterTLSConfig and the DSN.
  3. Use a built-in mode ('true', 'skip-verify', 'preferred') instead of a custom key when you do not need a custom tls.Config.
  4. If you set cfg.TLS directly on the Config, the TLSConfig-name lookup is skipped entirely.

Example fix

// before
db, _ := sql.Open("mysql", "user@tcp(host:3306)/db?tls=custom")
// after
mysql.RegisterTLSConfig("custom", &tls.Config{RootCAs: rootCAs, Certificates: certs})
db, _ := sql.Open("mysql", "user@tcp(host:3306)/db?tls=custom")
Defensive patterns

Strategy: validation

Validate before calling

// Verify the key is registered (or a reserved word) before opening.
func tlsKeyKnown(key string) bool {
    switch key { case "", "false", "true", "skip-verify", "preferred": return true }
    // reflect on the registry is not exported; simplest: keep your own set of registered keys
    return false // replace with your app's tracking of registered names
}

Try / catch

if _, err := mysql.ParseDSN(dsn); err != nil && strings.Contains(err.Error(), "unknown config name") {
    // register the TLS config under the right key, then retry
}

Prevention

When it happens

Trigger: A DSN with '?tls=custom' without a prior mysql.RegisterTLSConfig('custom', &tls.Config{...}) call; or the key was registered under a different name, or deregistered before connect.

Common situations: TLS registration code in main.go but the DSN is parsed earlier (init/test); typo between the RegisterTLSConfig key and the DSN; trying to register a reserved word ('true'/'skip-verify'/'preferred') which RegisterTLSConfig rejects; registration in a different process than the one opening the connection.

Related errors


AI-assisted analysis of go-sql-driver/mysql@c426bd9379 (2026-08-04). Data as JSON: /data/errors/c69fdd0bbeba1e72.json. Report an issue: GitHub.