AdguardTeam/AdGuardHome · error

unknown cipher %q

Error message

unknown cipher %q

What it means

ParseCiphers maps human-readable cipher-suite names (e.g. TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) to IDs; an unrecognized name yields this error. Only names present in the library's cipherSuites table are accepted.

Source

Thrown at internal/aghtls/aghtls.go:44

	l.DebugContext(ctx, "known ciphers", "ciphers", cipherSuites)
}

// cipherSuites are a name-to-ID mapping of cipher suites from crypto/tls.  It
// is filled by init.  It must not be modified.
var cipherSuites map[string]uint16

// ParseCiphers parses a slice of cipher suites from cipher names.
func ParseCiphers(cipherNames []string) (cipherIDs []uint16, err error) {
	if cipherNames == nil {
		return nil, nil
	}

	cipherIDs = make([]uint16, 0, len(cipherNames))
	for _, name := range cipherNames {
		id, ok := cipherSuites[name]
		if !ok {
			return nil, fmt.Errorf("unknown cipher %q", name)
		}

		cipherIDs = append(cipherIDs, id)
	}

	return cipherIDs, nil
}

// SaferCipherSuites returns a set of default cipher suites with vulnerable and
// weak cipher suites removed.
func SaferCipherSuites() (safe []uint16) {
	for _, s := range tls.CipherSuites() {
		switch s.ID {
		case
			tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
			tls.TLS_RSA_WITH_AES_128_CBC_SHA,
			tls.TLS_RSA_WITH_AES_256_CBC_SHA,
			tls.TLS_RSA_WITH_AES_128_CBC_SHA256,

View on GitHub (pinned to b41aefbe51)

Solutions

  1. Log the exact offending name and correct it against the supported table in aghtls (cipherSuites map)
  2. Remove TLS 1.3 ciphers from the list — they are always enabled and not settable this way
  3. Trim whitespace and drop empty tokens before parsing
  4. Copy a known-good cipher list from the project's docs/tests

Example fix

// before
ciphers := []string{"tls_ecdhe_rsa_with_aes_128_gcm_sha256", "TLS_AES_128_GCM_SHA256"}

// after
// only TLS 1.2-style names, exact case, from the supported table
ciphers := []string{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"}
Defensive patterns

Strategy: validation

Validate before calling

// validate against a known-good set before calling ParseCiphers:
for _, name := range cipherNames {
    if !slices.Contains(supportedCipherNames, name) { return fmt.Errorf("bad cipher %q", name) }
}

Type guard

func isValidCipherName(name string, table map[string]uint16) bool { _, ok := table[name]; return ok }

Try / catch

ids, err := aghtls.ParseCiphers(names)
if err != nil && strings.Contains(err.Error(), "unknown cipher") {
    // strip the offending name and re-validate, or fail config load with a clear message
}

Prevention

When it happens

Trigger: Passing a cipher name with a typo, wrong case, outdated name, or a name not in the supported cipherSuites map (e.g. TLS 1.3 suite names like TLS_AES_128_GCM_SHA256, which are configured differently, or CBC/3DES suites excluded from the table).

Common situations: Copying cipher lists from nginx/OpenSSL configs that include names Go's crypto/tls or this table doesn't support; upgrading Go versions where cipher lists changed; extra whitespace or commas producing empty/garbage tokens.

Related errors


AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27). Data as JSON: /api/errors/1769fd73f71f4204. Report an issue: GitHub.