AdguardTeam/AdGuardHome · error
another client uses the same MAC
Error message
another client %q uses the same MAC %q
What it means
Thrown when a client's MAC address is already assigned to another client in the index. MAC addresses uniquely identify persistent clients. The error reports the existing client name and the duplicated MAC.
Solutions
- Search stored clients for the MAC in the message and remove it from one of them (often a stale manually-added client)
- Let the DHCP/ARP runtime source own the MAC and delete the manual duplicate
- Pre-normalize the client list so MACs are unique before Add
Example fix
// before
client.MACs = []string{"AA:BB:CC:DD:EE:FF"} // already on client "phone"
s.Add(ctx, client)
// after
client.MACs = nil
s.Add(ctx, client) Defensive patterns
Strategy: validation
Validate before calling
usedMACs := map[string]string{}
for _, p := range existing {
for _, m := range p.MACs { usedMACs[strings.ToLower(m)] = p.Name }
}
for _, m := range c.MACs {
if owner, ok := usedMACs[strings.ToLower(m)]; ok && owner != c.Name { /* clash */ }
} Try / catch
if err := s.Add(ctx, c); err != nil && strings.Contains(err.Error(), "uses the same MAC") { c.MACs = nil; _ = s.Add(ctx, c) } Prevention
- Normalize MAC casing before comparison
- Avoid manually adding clients that DHCP/ARP sources already provide
When it happens
Trigger: Calling Storage.Add or Storage.Update with a client whose MAC equals the MAC of a different stored client, detected by clashesMAC.
Common situations: Two client entries (e.g. one from DHCP, one manual) carrying the same MAC, cloning client configs in the UI, imported client lists with duplicate MACs.
Related errors
- another client uses the same ClientID
- another client uses the same IP
- another client uses the same subnet
- invalid tag
- invalid upstream servers
AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27).
Data as JSON: /api/errors/ac36c02a262e2edd.
Report an issue: GitHub.
Appendix: source
Thrown at internal/client/index.go:133
p := ci.uidToClient[existing]
return fmt.Errorf("another client %q uses the same ClientID %q", p.Name, id)
}
}
p, ip := ci.clashesIP(c)
if p != nil {
return fmt.Errorf("another client %q uses the same IP %q", p.Name, ip)
}
p, s := ci.clashesSubnet(c)
if p != nil {
return fmt.Errorf("another client %q uses the same subnet %q", p.Name, s)
}
p, mac := ci.clashesMAC(c)
if p != nil {
return fmt.Errorf("another client %q uses the same MAC %q", p.Name, mac)
}
return nil
}
// clashesName returns existing persistent client with the same name as c or
// nil. c must be non-nil.
func (ci *index) clashesName(c *Persistent) (existing *Persistent) {
existing, ok := ci.findByName(c.Name)
if !ok {
return nil
}
if existing.UID != c.UID {
return existing
}
return nilView on GitHub (pinned to b41aefbe51)