AdguardTeam/AdGuardHome · critical
adding client %q at index %d: %w
Error message
adding client %q at index %d: %w
What it means
Constructor error from NewStorage: one of the InitialClients in the supplied configuration failed to be added, and the error is wrapped with the client's name and its position in the list. The inner error is typically one of the clash or validation errors from Add.
Source
Thrown at internal/client/storage.go:195
s = &Storage{
logger: conf.Logger,
mu: &sync.Mutex{},
index: newIndex(),
runtimeIndex: newRuntimeIndex(),
upstreamManager: newUpstreamManager(conf.BaseLogger, conf.Clock),
dhcp: conf.DHCP,
etcHosts: conf.EtcHosts,
arpDB: conf.ARPDB,
done: make(chan struct{}),
allowedTags: tags,
arpClientsUpdatePeriod: conf.ARPClientsUpdatePeriod,
runtimeSourceDHCP: conf.RuntimeSourceDHCP,
}
for i, p := range conf.InitialClients {
err = s.Add(ctx, p)
if err != nil {
return nil, fmt.Errorf("adding client %q at index %d: %w", p.Name, i, err)
}
}
s.ReloadARP(ctx)
return s, nil
}
// type check
var _ service.Interface = (*Storage)(nil)
// Start implements the [service.Interface] for *Storage. It starts the
// goroutines for updating the runtime client information.
func (s *Storage) Start(ctx context.Context) (err error) {
go s.periodicARPUpdate(ctx)
go s.handleHostsUpdates(ctx)
return nilView on GitHub (pinned to b41aefbe51)
Solutions
- Look at the wrapped error to see the actual cause and the client name/index from the message
- Fix or remove the offending client at that index in InitialClients and restart
- Validate the whole client list (uniqueness of IDs/IP/MAC, upstream parsing, known tags) before handing it to NewStorage
Example fix
// before
conf.InitialClients = []aghclient.PersistentClient{
{Name: "a", IP: "10.0.0.1"},
{Name: "b", IP: "10.0.0.1"}, // duplicate -> NewStorage fails at index 1
}
// after
conf.InitialClients = []aghclient.PersistentClient{
{Name: "a", IP: "10.0.0.1"},
{Name: "b", IP: "10.0.0.2"},
} Defensive patterns
Strategy: validation
Validate before calling
for i := range conf.InitialClients {
if err := validateClient(&conf.InitialClients[i]); err != nil { return fmt.Errorf("initial client %d: %w", i, err) }
}
// plus duplicate-ID/IP/MAC checks across the list Try / catch
s, err := client.NewStorage(ctx, conf)
if err != nil && strings.Contains(err.Error(), "adding client") { /* log, fall back to empty storage or last good config */ } Prevention
- Lint the whole client list before startup
- Keep the previous config file so a failed constructor can fall back to it
When it happens
Trigger: Passing conf.InitialClients containing an invalid client (bad upstreams, unknown tag) or one that clashes with an earlier entry (duplicate ClientID, IP, subnet, or MAC). The failure index in the message points at the offending element.
Common situations: Loading a hand-edited or migrated YAML config with duplicated IPs/MACs, stale tags after a settings change, or upstream typos; first startup after editing clients in the config file.
Related errors
- loading sessions: %w
- deleting sessions: %w
- dns.bind_hosts at index %d is not a valid ip address
- writing new config: %w
- validating tcp ports: %w
AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27).
Data as JSON: /api/errors/167ce8db9b039b71.
Report an issue: GitHub.