AdguardTeam/AdGuardHome · error

persistent client at index %d: unexpected type %T

Error message

persistent client at index %d: unexpected type %T

What it means

During migration to schema 22, an element of the persistent clients array is not a YAML object (mapping). Each client must be a map so its "whois"/services field can be restructured; scalars or nested arrays abort the migration.

Source

Thrown at internal/configmigrate/v22.go:53

	diskConf["schema_version"] = 22

	const field = "blocked_services"

	clients, ok, err := fieldVal[yobj](diskConf, "clients")
	if !ok {
		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",
			},
		}
	}

View on GitHub (pinned to b41aefbe51)

Solutions

  1. Find the clients array and make every element a mapping (name, ids, etc.)
  2. Remove malformed client entries that are not real client definitions
  3. Re-run the migration

Example fix

# before
clients:
  - "laptop"

# after
clients:
  - name: laptop
    ids:
      - laptop
Defensive patterns

Strategy: type-guard

Validate before calling

for i, c := range clients {
    if _, ok := c.(map[string]any); !ok { /* clients[%d] must be a mapping */ _ = i }
}

Type guard

func isObj(v any) bool { _, ok := v.(map[string]any); return ok }

Try / catch

if err != nil && strings.Contains(err.Error(), "expected object") { /* rewrite offending client entry as a mapping and retry */ }

Prevention

When it happens

Trigger: Migrating a config whose clients list contains a string, number, or array element instead of a mapping, e.g. `clients: [ "laptop" ]`.

Common situations: Hand-rolled configs where a client was written as a plain name, or list-vs-map confusion after editing the YAML.

Related errors


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