{"record":{"id":"e9e3b22cbe0d4077","repo":"AdguardTeam/AdGuardHome","slug":"another-client-q-uses-the-same-subnet-q","errorCode":null,"errorMessage":"another client %q uses the same subnet %q","messagePattern":"another client %q uses the same subnet %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/index.go","lineNumber":128,"sourceCode":"\t}\n\n\tfor _, id := range c.ClientIDs {\n\t\texisting, ok := ci.clientIDToUID[id]\n\t\tif ok && existing != c.UID {\n\t\t\tp := ci.uidToClient[existing]\n\n\t\t\treturn fmt.Errorf(\"another client %q uses the same ClientID %q\", p.Name, id)\n\t\t}\n\t}\n\n\tp, ip := ci.clashesIP(c)\n\tif p != nil {\n\t\treturn fmt.Errorf(\"another client %q uses the same IP %q\", p.Name, ip)\n\t}\n\n\tp, s := ci.clashesSubnet(c)\n\tif p != nil {\n\t\treturn fmt.Errorf(\"another client %q uses the same subnet %q\", p.Name, s)\n\t}\n\n\tp, mac := ci.clashesMAC(c)\n\tif p != nil {\n\t\treturn fmt.Errorf(\"another client %q uses the same MAC %q\", p.Name, mac)\n\t}\n\n\treturn nil\n}\n\n// clashesName returns existing persistent client with the same name as c or\n// nil.  c must be non-nil.\nfunc (ci *index) clashesName(c *Persistent) (existing *Persistent) {\n\texisting, ok := ci.findByName(c.Name)\n\tif !ok {\n\t\treturn nil\n\t}\n","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/client/index.go#L110-L146","documentation":"Thrown when the client's subnet (/24 or configured subnet range) overlaps with another client's subnet in the index. AdGuard Home requires persistent clients to map to disjoint subnet ranges. The error names the conflicting client and subnet.","triggerScenarios":"Calling Storage.Add or Storage.Update with a client whose subnet (derived from its IP) matches the subnet of a different stored client, as detected by clashesSubnet.","commonSituations":"Defining multiple clients inside the same /24 when subnet-based identification is enabled, migrating configs where subnet clients were keyed by broader ranges.","solutions":["Check the client named in the message and either disable one client's subnet identification or move the clients into distinct subnets","Use exact IP or ClientID identification instead of subnet identification for dense networks","Use Update on the existing client instead of adding a second one covering the same subnet"],"exampleFix":"// before\nclient.UseSubnets = true; client.IP = \"10.0.0.5\"  // \"10.0.0.0/24\" already claimed\ns.Add(ctx, client)\n\n// after\nclient.UseSubnets = false\ns.Add(ctx, client)","handlingStrategy":"validation","validationCode":"func subnetClash(p, c client.Persistent) bool {\n    return p.UseSubnets && c.UseSubnets && p.IP.As4()[0:3] == c.IP.As4()[0:3] // /24 heuristic\n}","typeGuard":null,"tryCatchPattern":"if err := s.Update(ctx, name, c); err != nil && strings.Contains(err.Error(), \"uses the same subnet\") { c.UseSubnets = false; _ = s.Update(ctx, name, c) }","preventionTips":["Only enable subnet identification for clients in distinct subnets","Prefer exact IP or ClientID identification in dense /24 networks"],"tags":["client","subnet","duplicate","validation"],"backgroundTag":"duplicate-identifier-conflict","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}