AdguardTeam/AdGuardHome · error
unknown ipset
Error message
unknown ipset %q
What it means
A config line references an ipset name that is not present in the map of sets currently known on the system (built from the initial list query and earlier processing).
Solutions
- Create the ipset before starting: 'ipset create <name> hash:ip'
- Check exact spelling/case against 'ipset list' output
- Persist sets so they survive reboots/firewall restarts
Example fix
# before # config references adguard-block but set missing # after ipset create adguard-block hash:ip family inet timeout 0
Defensive patterns
Strategy: validation
Validate before calling
func setExists(name string) bool {
out, _ := exec.Command("ipset", "list", name).CombinedOutput()
return !bytes.Contains(out, []byte("doesn't exist")) && len(out) > 0
} Try / catch
if err != nil && strings.Contains(err.Error(), "unknown ipset") {
_ = exec.Command("ipset", "create", name, "hash:ip").Run()
// retry init
} Prevention
- Provision sets before service start; re-check after every firewall reload
- Name sets exactly (case-sensitive) as in config
When it happens
Trigger: m.ipsets looks up names[i] in currentlyKnown and misses: set not created, typo, or race where the set was destroyed between listing and lookup.
Common situations: Forgetting 'ipset create' before starting the service, name case/spelling mismatch, or sets wiped by firewall reload.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- getting ipsets from config line at idx
- config line at idx
- getting ipsets
- invalid value : empty ipset name
- invalid value : expected one slash
AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27).
Data as JSON: /api/errors/c87a3405710e913a.
Report an issue: GitHub.
Appendix: source
Thrown at internal/ipset/ipset_linux.go:343
return props{
name: name,
typeName: typeName,
family: family,
isPersistent: false,
}, nil
}
// ipsets returns ipset properties of currently known ipsets. It also makes an
// additional ipset header data query if needed.
func (m *manager) ipsets(
ctx context.Context,
names []string,
currentlyKnown map[string]props,
) (sets []props, err error) {
for _, n := range names {
p, ok := currentlyKnown[n]
if !ok {
return nil, fmt.Errorf("unknown ipset %q", n)
}
if p.family != netfilter.ProtoIPv4 && p.family != netfilter.ProtoIPv6 {
m.logger.DebugContext(
ctx,
"got unexpected ipset family while getting set properties",
"set_name", p.name,
"set_type", p.typeName,
"set_family", p.family,
)
p, err = m.ipsetProps(n)
if err != nil {
return nil, fmt.Errorf("%q %q making header query: %w", p.name, p.typeName, err)
}
}
m.nameToIpset[n] = pView on GitHub (pinned to b41aefbe51)