XTLS/Xray-core · error
unknown nonIPQuery: {}
Error message
unknown nonIPQuery: {} What it means
Thrown while compiling the deprecated 'nonIPQuery' setting of a DNS outbound into internal rules: the mode string is not one of the accepted values. buildLegacyDNSPolicy() accepts only "" (defaults to reject), "reject", "drop", and "skip"; anything else is rejected. This runs only on the legacy code path (nonIPQuery/blockTypes present without 'rules').
Source
Thrown at infra/conf/dns_proxy.go:130
}
config.Rule = append(config.Rule, rule)
}
return config, nil
}
// todo: remove legacy
func (c *DNSOutboundConfig) buildLegacyDNSPolicy() ([]*dns.DNSRuleConfig, error) {
rules := make([]*dns.DNSRuleConfig, 0, 3)
mode := "reject"
if c.NonIPQuery != nil && *c.NonIPQuery != "" {
mode = *c.NonIPQuery
}
switch mode {
case "", "reject", "drop", "skip":
default:
return nil, errors.New("unknown nonIPQuery: ", mode)
}
if c.BlockTypes != nil && len(*c.BlockTypes) > 0 {
rule := &dns.DNSRuleConfig{Action: dns.RuleAction_Drop}
if mode == "reject" {
rule.Action = dns.RuleAction_Return
rule.RCode = 5
}
for _, qType := range *c.BlockTypes {
if qType < 0 || qType > 65535 {
return nil, errors.New("legacy blockTypes qType out of range: ", qType)
}
rule.QType = append(rule.QType, qType)
}
rules = append(rules, rule)
}
{View on GitHub (pinned to 7d214f8b09)
Solutions
- Set "nonIPQuery" to "reject", "drop", "skip", or remove it entirely (default is reject).
- Prefer migrating to the "rules" array, which supersedes nonIPQuery and gives per-qType control.
- Check spelling/case: values are matched literally after the nil/empty default, so "Drop" works via strings equality? No — match is exact lowercase; use lowercase values.
Example fix
// before "nonIPQuery": "block" // after "nonIPQuery": "drop"
Defensive patterns
Strategy: validation
Validate before calling
var validNonIPQuery = map[string]bool{"": true, "reject": true, "drop": true, "skip": true}
if c.NonIPQuery != nil && !validNonIPQuery[strings.ToLower(*c.NonIPQuery)] {
return fmt.Errorf("unknown nonIPQuery %q", *c.NonIPQuery)
} Prevention
- Use only reject/drop/skip (lowercase) for nonIPQuery, or omit it.
- Plan migration to rules; the legacy path prints deprecation warnings.
When it happens
Trigger: A DNS outbound with "nonIPQuery": "allow" or "block" or any word other than reject/drop/skip, while not using the "rules" array. The switch default branch fires immediately.
Common situations: Guessing allowed values instead of checking docs; configs ported from tools whose semantics differ (e.g. dnsmasq 'refuse', AdGuard 'refused').
Related errors
- unknown action: {}
- rCode out of range: {}
- legacy nonIPQuery and blockTypes cannot be mixed with rules
- legacy blockTypes qType out of range: {}
- empty domains & empty resolvers
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/b07867213f2aecc0.
Report an issue: GitHub.