XTLS/Xray-core · error

Unsupported cipher.

Error message

Unsupported cipher.

What it means

Config-time error from Account.getCipher(): the configured CipherType enum value matched no case in the switch. Xray's protobuf config deserializes unknown numeric cipher values without complaint, so this error is typically the first signal of a typo'd or unsupported method name in the JSON config, or a cipher removed/renamed across Xray versions.

Source

Thrown at proxy/shadowsocks/config.go:89

		return &AEADCipher{
			KeyBytes:        32,
			IVBytes:         32,
			AEADAuthCreator: createAesGcm,
		}, nil
	case CipherType_CHACHA20_POLY1305:
		return &AEADCipher{
			KeyBytes:        32,
			IVBytes:         32,
			AEADAuthCreator: createChaCha20Poly1305,
		}, nil
	case CipherType_XCHACHA20_POLY1305:
		return &AEADCipher{
			KeyBytes:        32,
			IVBytes:         32,
			AEADAuthCreator: createXChaCha20Poly1305,
		}, nil
	default:
		return nil, errors.New("Unsupported cipher.")
	}
}

// AsAccount implements protocol.AsAccount.
func (a *Account) AsAccount() (protocol.Account, error) {
	Cipher, err := a.getCipher()
	if err != nil {
		return nil, errors.New("failed to get cipher").Base(err)
	}
	return &MemoryAccount{
		Cipher:     Cipher,
		CipherType: a.CipherType,
		Key:        passwordToCipherKey([]byte(a.Password), Cipher.KeySize()),
		Password:   a.Password,
	}, nil
}

// Cipher is an interface for all Shadowsocks ciphers.

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Set the method to a supported AEAD value: aes-128-gcm, aes-256-gcm, chacha20-poly1305, or xchacha20-poly1305.
  2. Run xray run -test (or -config with validation) after editing to catch config errors before runtime.
  3. If you need legacy stream ciphers, use a Shadowsocks-libev server or an older fork — current Xray deliberately dropped them.
  4. Regenerate the config rather than hand-editing enum numbers.

Example fix

// before
{ "method": "aes-256-cfb", "password": "..." }
// after
{ "method": "aes-256-gcm", "password": "..." }
Defensive patterns

Strategy: validation

Validate before calling

var supportedSSCiphers = map[string]bool{
  "aes-128-gcm": true, "aes-256-gcm": true,
  "chacha20-poly1305": true, "xchacha20-poly1305": true,
}
func validateCipher(method string) error {
  if !supportedSSCiphers[method] {
    return fmt.Errorf("unsupported cipher %q; use an AEAD cipher", method)
  }
  return nil
}

Type guard

func isSupportedSSCipher(m string) bool {
  switch m {
  case "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "xchacha20-poly1305":
    return true
  }
  return false
}

Prevention

When it happens

Trigger: Setting cipherType in a shadowsocks account to a value outside the supported set (legacy stream ciphers like rc4-md5, aes-256-cfb after removal, or a raw number from a mis-generated config); loading a config produced for a fork with extra ciphers.

Common situations: Migrating from Shadowsocks-libev or old V2Ray configs using stream ciphers; copy-paste typos ('aes-128-gcm ' with space, 'chacha20-ietf-poly1305' vs 'xchacha20-20-poly1305'); configs written for forks whose enums drifted.

Related errors


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/18f3c4421b19e8d6. Report an issue: GitHub.