AdguardTeam/AdGuardHome · error

persistent client at index %d: %w

Error message

persistent client at index %d: %w

What it means

During migration to schema 22, extracting the services field from a persistent client object failed (fieldVal error), wrapped with the client's index. Typically the field exists but has the wrong type (e.g. whois is a string where an array is expected).

Source

Thrown at internal/configmigrate/v22.go:59

		return err
	}

	persistent, ok, err := fieldVal[yarr](clients, "persistent")
	if !ok {
		return err
	}

	for i, p := range persistent {
		var c yobj
		c, ok = p.(yobj)
		if !ok {
			return fmt.Errorf("persistent client at index %d: unexpected type %T", i, p)
		}

		var services yarr
		services, ok, err = fieldVal[yarr](c, field)
		if err != nil {
			return fmt.Errorf("persistent client at index %d: %w", i, err)
		} else if !ok {
			continue
		}

		c[field] = yobj{
			"ids": services,
			"schedule": yobj{
				"time_zone": "Local",
			},
		}
	}

	return nil
}

View on GitHub (pinned to b41aefbe51)

Solutions

  1. Check the client at the index in the message; make its whois field either absent or a list
  2. Set `whois: []` if you just need a syntactically valid empty value
  3. Retry Migrate

Example fix

# before
- name: laptop
  whois: "example.com"

# after
- name: laptop
  whois:
    - example.com
Defensive patterns

Strategy: type-guard

Validate before calling

for _, c := range clients {
    obj, ok := c.(map[string]any)
    if !ok { continue }
    if w, ok := obj["whois"]; ok {
        if _, ok := w.([]any); !ok { /* whois must be a list or removed */ }
    }
}

Type guard

func isStringArray(v any) bool { _, ok := v.([]any); if !ok { return false }; for _, e := range v.([]any) { if _, ok := e.(string); !ok { return false } }; return true }

Try / catch

if err != nil && strings.Contains(err.Error(), "persistent client at index") { /* check client at that index, coerce whois to a list, retry */ }

Prevention

When it happens

Trigger: Migrating a config where a client's whois/services field is present but not an array (yarr), e.g. `whois: true` or `whois: "example.com"`.

Common situations: Hand-edited clients where the whois field was replaced by a scalar; older or third-party tooling writing the field with the wrong shape.

Related errors


AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27). Data as JSON: /api/errors/6e67abd865721697. Report an issue: GitHub.