AdguardTeam/AdGuardHome · error
another client %q uses the same ClientID %q
Error message
another client %q uses the same ClientID %q
What it means
Thrown when adding or updating a persistent client whose ClientID collides with a different client already in the storage index. The index maps each ClientID to a unique UID, so two distinct clients cannot share a ClientID. The error names the conflicting client and the duplicated ID.
Source
Thrown at internal/client/index.go:117
return fmt.Errorf("another client %q uses the same uid", p.Name)
}
return nil
}
// clashes returns an error if the index contains a different persistent client
// with at least a single identifier contained by c. c must be non-nil.
func (ci *index) clashes(c *Persistent) (err error) {
if p := ci.clashesName(c); p != nil {
return fmt.Errorf("another client uses the same name %q", p.Name)
}
for _, id := range c.ClientIDs {
existing, ok := ci.clientIDToUID[id]
if ok && existing != c.UID {
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)
}
View on GitHub (pinned to b41aefbe51)
Solutions
- Inspect the stored clients and find the client named in the error message; remove the duplicated ID from one of the two clients
- If the two entries should be the same client, update the existing one instead of adding a new one
- Deduplicate ClientIDs across the whole initial client list before passing it to NewStorage
Example fix
// before
client.ClientIDs = []string{"alice"} // already used by client "laptop"
_ = s.Add(ctx, client)
// after
client.ClientIDs = []string{"alice-laptop"}
_ = s.Add(ctx, client) Defensive patterns
Strategy: validation
Validate before calling
func hasClientIDClash(persistent []client.Persistent, c client.Persistent) bool {
for _, p := range persistent {
if p.UID == c.UID { continue }
for _, id := range c.ClientIDs {
if slices.Contains(p.ClientIDs, id) { return true }
}
}
return false
} Try / catch
err := s.Add(ctx, c)
if err != nil && strings.Contains(err.Error(), "uses the same ClientID") {
// resolve conflict or fall back to Update on existing client
} Prevention
- Maintain a set of used ClientIDs and check before every Add/Update
- Treat imports as upserts: match on existing IDs before inserting
When it happens
Trigger: Calling Storage.Add or Storage.Update (or the internal index clashes check) with a Client whose ClientIDs slice contains an ID already registered under another client's UID (i.e. a different Name/UID).
Common situations: Migrating or importing client lists that contain duplicate IDs (e.g. the same TLS CN or username appearing twice), copying a client configuration and forgetting to change its IDs, or UI edits that merge two clients into overlapping ID sets.
Related errors
- another client %q uses the same IP %q
- another client %q uses the same subnet %q
- another client %q uses the same MAC %q
- invalid upstream servers: %w
- invalid tag: %q
AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27).
Data as JSON: /api/errors/6d7f658df9387d76.
Report an issue: GitHub.