XTLS/Xray-core · error

VLESS users: please add/set "encryption":"none" for every us

Error message

VLESS users: please add/set "encryption":"none" for every user

What it means

Thrown by VLessOutboundConfig.Build() when a user's "encryption" field is empty (and not a valid mlkem768x25519plus post-quantum spec). Unlike VMess, VLESS has no implicit default encryption: the protocol requires the exact string "none" so that the intent is explicit. Omitting the field — very common when copying VMess-style configs — produces this error.

Source

Thrown at infra/conf/vless.go:372

				padding := 0
				for _, r := range s[3:] {
					if len(r) < 20 {
						padding += len(r) + 1
						continue
					}
					if b, _ := base64.RawURLEncoding.DecodeString(r); len(b) != 32 && len(b) != 1184 {
						return false
					}
				}
				account.Encryption = account.Encryption[27+len(s[2]):]
				if padding > 0 {
					account.Padding = account.Encryption[:padding-1]
					account.Encryption = account.Encryption[padding:]
				}
				return true
			}() && account.Encryption != "none" {
				if account.Encryption == "" {
					return nil, errors.New(`VLESS users: please add/set "encryption":"none" for every user`)
				}
				return nil, errors.New(`VLESS users: unsupported "encryption": ` + account.Encryption)
			}

			user.Account = serial.ToTypedMessage(account)
			spec.User = user
			break
		}
		config.Vnext = spec
		break
	}

	return config, nil
}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Add "encryption":"none" to every user object
  2. Or set "encryption":"none" at the outbound top level in the simplified style
  3. Regenerate the config/link with an up-to-date generator that always emits the field

Example fix

// before
"users": [ { "id": "b831381d-6324-4d53-ad4f-8cda48b30811" } ]
// after
"users": [ { "id": "b831381d-6324-4d53-ad4f-8cda48b30811", "encryption": "none" } ]
Defensive patterns

Strategy: validation

Validate before calling

func validateVlessEncryption(cfg map[string]any) error {
	outbounds, _ := cfg["outbounds"].([]any)
	for _, ob := range outbounds {
		m, _ := ob.(map[string]any)
		if p, _ := m["protocol"].(string); p != "vless" { continue }
		settings, _ := m["settings"].(map[string]any)
		if e, ok := settings["encryption"].(string); ok && e != "" { continue }
		vnext, _ := settings["vnext"].([]any)
		for _, v := range vnext {
			ep, _ := v.(map[string]any)
			users, _ := ep["users"].([]any)
			for i, u := range users {
				um, _ := u.(map[string]any)
				if e, _ := um["encryption"].(string); e == "" {
					return fmt.Errorf("outbound %v: vnext.users[%d] missing encryption", m["tag"], i)
				}
			}
		}
	}
	return nil
}

Type guard

func vlessEncryptionSet(u map[string]any) bool {
	e, ok := u["encryption"].(string)
	return ok && e != ""
}

Prevention

When it happens

Trigger: "users":[{"id":"uuid"}] with no "encryption" key; "encryption":"" (empty string). Both full style and share links converted without the encryption field.

Common situations: Converting a VMess outbound to VLESS by changing only protocol and id; configs from tutorials that predate the mandatory-encryption rule; older Xray versions that tolerated a missing field, breaking after upgrade.

Related errors


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