XTLS/Xray-core · error

legacy nonIPQuery and blockTypes cannot be mixed with rules

Error message

legacy nonIPQuery and blockTypes cannot be mixed with rules

What it means

Thrown when an Xray DNS outbound config simultaneously declares the deprecated 'nonIPQuery'/'blockTypes' fields and the newer 'rules' array. The two mechanisms compile to overlapping rule sets, so the builder refuses to merge them and prints this error after the deprecation warning path detects both. It exists to force an explicit migration to 'rules'.

Source

Thrown at infra/conf/dns_proxy.go:97

	}
	if c.Port != 0 {
		c.RewritePort = c.Port
	}
	config := &dns.Config{
		RewriteServer: &net.Endpoint{
			Network: c.RewriteNetwork.Build(),
			Port:    uint32(c.RewritePort),
		},
		UserLevel: c.UserLevel,
	}
	if c.RewriteAddress != nil {
		config.RewriteServer.Address = c.RewriteAddress.Build()
	}

	// todo: remove legacy
	if c.NonIPQuery != nil || c.BlockTypes != nil {
		if c.Rules != nil {
			return nil, errors.New("legacy nonIPQuery and blockTypes cannot be mixed with rules")
		}
		errors.PrintDeprecatedFeatureWarning(`"nonIPQuery" and "blockTypes"`, `"rules"`)
		rules, err := c.buildLegacyDNSPolicy()
		if err != nil {
			return nil, err
		}
		config.Rule = rules
		return config, nil
	}

	for _, r := range c.Rules {
		rule, err := r.Build()
		if err != nil {
			return nil, err
		}
		config.Rule = append(config.Rule, rule)
	}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Delete "nonIPQuery" and "blockTypes" from the DNS outbound and express the same policy with "rules".
  2. Map legacy values: nonIPQuery "drop" -> rule action "drop" on the non-A/AAAA qtypes; "reject" -> action "return" with rcode 5; blockTypes -> a rule listing those qTypes.
  3. Keep only the legacy fields (remove "rules") if you cannot migrate yet — one or the other, never both.

Example fix

// before
"nonIPQuery": "drop",
"blockTypes": [255],
"rules": [{"action": "drop", "qType": [255]}]

// after
"rules": [
  {"action": "drop", "qType": [255]},
  {"action": "hijack", "qType": [1, 28]}
]
Defensive patterns

Strategy: validation

Validate before calling

if (c.nonIPQuery !== undefined || c.blockTypes !== undefined) && Array.isArray(c.rules) && c.rules.length > 0 {
    throw new Error('nonIPQuery/blockTypes cannot be mixed with rules; migrate to rules');
}

Prevention

When it happens

Trigger: A DNS outbound JSON containing e.g. "nonIPQuery": "drop" or "blockTypes": [255] together with a non-empty "rules": [...] in the same object. Checked at the top of DNSOutboundConfig.Build() before rules are compiled.

Common situations: Upgrading an old config to the rules syntax but leaving the legacy fields in place 'just in case'; merging example snippets from docs of different Xray versions.

Related errors


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