XTLS/Xray-core · error

VLESS reverse: invalid "sniffing" config

Error message

VLESS reverse: invalid "sniffing" config

What it means

Thrown by VLessReverseConfig.Build() when the optional "sniffing" object inside a VLESS reverse config fails to build. The reverse builder delegates to SniffingConfig.Build() and wraps any failure with this message; the underlying cause is attached via .Base(err). Typical inner failures are an invalid "destOnly"/"target" combination or unrecognized sniffing targets.

Source

Thrown at infra/conf/vless.go:232

	return config, nil
}

type VLessReverseConfig struct {
	Tag      string          `json:"tag"`
	Sniffing *SniffingConfig `json:"sniffing"`
}

func (c *VLessReverseConfig) Build() (*vless.Reverse, error) {
	if c.Tag == "" {
		return nil, errors.New(`VLESS reverse: "tag" can't be empty`)
	}
	r := &vless.Reverse{
		Tag: c.Tag,
	}
	if c.Sniffing != nil {
		sc, err := c.Sniffing.Build()
		if err != nil {
			return nil, errors.New(`VLESS reverse: invalid "sniffing" config`).Base(err)
		}
		r.Sniffing = sc
	}
	return r, nil
}

type VLessOutboundVnext struct {
	Address *Address          `json:"address"`
	Port    uint16            `json:"port"`
	Users   []json.RawMessage `json:"users"`
}

type VLessOutboundConfig struct {
	Address    *Address              `json:"address"`
	Port       uint16                `json:"port"`
	Level      uint32                `json:"level"`
	Email      string                `json:"email"`
	Id         string                `json:"id"`

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Inspect the wrapped inner error (err) — it names the exact sniffing field that failed
  2. Use only supported sniffing targets: "http", "tls", "quic", "fakedns", "fakedns+others" as appropriate for your version
  3. Simplify: start with "sniffing":{"enabled":true,"target":["http","tls"]} and add fields back one at a time
  4. Remove "sniffing" from the reverse object if content sniffing is not needed for the tunnel

Example fix

// before
"reverse": { "tag": "t", "sniffing": { "enabled": true, "destOnly": "yes" } }
// after
"reverse": { "tag": "t", "sniffing": { "enabled": true, "target": ["http", "tls"] } }
Defensive patterns

Strategy: try-catch

Validate before calling

func validateReverseSniffing(rev map[string]any) error {
	sn, ok := rev["sniffing"].(map[string]any)
	if !ok { return nil }
	for _, t := range []string{"enabled"} {
		if v, ok := sn[t]; ok {
			if _, ok := v.(bool); !ok {
				return fmt.Errorf("reverse.sniffing.%s must be boolean", t)
			}
		}
	}
	if targets, ok := sn["target"].([]any); ok {
		valid := map[string]bool{"http": true, "tls": true, "quic": true, "fakedns": true}
		for _, t := range targets {
			s, _ := t.(string)
			if !valid[s] {
				return fmt.Errorf("reverse.sniffing.target %q not supported", s)
			}
		}
	}
	return nil
}

Try / catch

config, err := jsonToCoreConfig(raw)
if err != nil {
	var buildErr *errors.Error
	if strings.Contains(err.Error(), `VLESS reverse: invalid "sniffing" config`) {
		// unwrap and log the Base cause, point the user at the sniffing block
		log.Printf("reverse sniffing misconfigured: %v", errors.Unwrap(err))
	}
	return err
}

Prevention

When it happens

Trigger: "reverse":{"tag":"x","sniffing":{"enabled":true,"destOnly":"yes"}} — wrong field types; sniffing targets that are not in the supported list (http, tls, quic, fakedns, etc.); malformed regex-only sniffing options.

Common situations: Copying a sniffing block from an inbound (where fields differ) into the reverse object; version drift where supported sniffing target names changed between Xray releases.

Related errors


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