caddyserver/caddy · error

unsupported cipher suite: %s

Error message

unsupported cipher suite: %s

What it means

Returned by buildStandardTLSConfig when a ciphers/cipher_suites entry is not found in the supported list (CipherSuiteID returns 0). Caddy only accepts the IANA-style names it has registered; TLS 1.3 suites are not configurable in Go's TLS stack, and unknown or misspelled names fail here.

Source

Thrown at modules/caddytls/connpolicy.go:345

		// session ticket key rotation
		tlsApp.SessionTickets.register(cfg)
		ctx.OnCancel(func() {
			// do cleanup when the context is canceled because,
			// though unlikely, it is possible that a context
			// needing a TLS server config could exist for less
			// than the lifetime of the whole app
			tlsApp.SessionTickets.unregister(cfg)
		})
	}

	// TODO: Clean up session ticket active locks in storage if app (or process) is being closed!

	// add all the cipher suites in order, without duplicates
	cipherSuitesAdded := make(map[uint16]struct{})
	for _, csName := range p.CipherSuites {
		csID := CipherSuiteID(csName)
		if csID == 0 {
			return fmt.Errorf("unsupported cipher suite: %s", csName)
		}
		if _, ok := cipherSuitesAdded[csID]; !ok {
			cipherSuitesAdded[csID] = struct{}{}
			cfg.CipherSuites = append(cfg.CipherSuites, csID)
		}
	}

	// add all the curve preferences in order, without duplicates
	curvesAdded := make(map[tls.CurveID]struct{})
	for _, curveName := range p.Curves {
		curveID := SupportedCurves[curveName]
		if _, ok := curvesAdded[curveID]; !ok {
			curvesAdded[curveID] = struct{}{}
			cfg.CurvePreferences = append(cfg.CurvePreferences, curveID)
		}
	}

	// ensure ALPN includes the ACME TLS-ALPN protocol

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Remove the offending name shown in the error
  2. Restrict cipher lists to TLS 1.2 suites from Go's supported set and drop TLS_AES_/TLS_CHACHA20_ names (1.3 suites are always-on)
  3. Re-copy a known-good list from Caddy's documentation
  4. Validate config with 'caddy validate' after editing

Example fix

# before
tls {
	ciphers TLS_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
}

# after (TLS 1.3 suites are not configurable)
tls {
	ciphers TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
}
Defensive patterns

Strategy: validation

Validate before calling

// In Go, validate names against Caddy's registry before accepting user input:
func validCipher(name string) bool {
	return caddytls.CipherSuiteID(name) != 0
}

Prevention

When it happens

Trigger: A tls block listing a cipher name not in the supported map: misspellings, older GCM names, TLS 1.3 suite names (TLS_AES_128_GCM_SHA256 etc.), or names from other servers' docs. Applies per connection policy during Provision.

Common situations: Copying cipher lists from nginx/Apache/Mozilla SSL config generator output that includes names Caddy/Go do not support; hardening guides mixing TLS 1.2 and 1.3 suites; trailing whitespace or case differences.

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/da9633a441c34f41. Report an issue: GitHub.