{"record":{"id":"6e67abd865721697","repo":"AdguardTeam/AdGuardHome","slug":"persistent-client-at-index-d-w","errorCode":null,"errorMessage":"persistent client at index %d: %w","messagePattern":"persistent client at index (.+?): %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configmigrate/v22.go","lineNumber":59,"sourceCode":"\t\treturn err\n\t}\n\n\tpersistent, ok, err := fieldVal[yarr](clients, \"persistent\")\n\tif !ok {\n\t\treturn err\n\t}\n\n\tfor i, p := range persistent {\n\t\tvar c yobj\n\t\tc, ok = p.(yobj)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"persistent client at index %d: unexpected type %T\", i, p)\n\t\t}\n\n\t\tvar services yarr\n\t\tservices, ok, err = fieldVal[yarr](c, field)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"persistent client at index %d: %w\", i, err)\n\t\t} else if !ok {\n\t\t\tcontinue\n\t\t}\n\n\t\tc[field] = yobj{\n\t\t\t\"ids\": services,\n\t\t\t\"schedule\": yobj{\n\t\t\t\t\"time_zone\": \"Local\",\n\t\t\t},\n\t\t}\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":41,"sourceCodeEnd":74,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/configmigrate/v22.go#L41-L74","documentation":"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).","triggerScenarios":"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\"`.","commonSituations":"Hand-edited clients where the whois field was replaced by a scalar; older or third-party tooling writing the field with the wrong shape.","solutions":["Check the client at the index in the message; make its whois field either absent or a list","Set `whois: []` if you just need a syntactically valid empty value","Retry Migrate"],"exampleFix":"# before\n- name: laptop\n  whois: \"example.com\"\n\n# after\n- name: laptop\n  whois:\n    - example.com","handlingStrategy":"type-guard","validationCode":"for _, c := range clients {\n    obj, ok := c.(map[string]any)\n    if !ok { continue }\n    if w, ok := obj[\"whois\"]; ok {\n        if _, ok := w.([]any); !ok { /* whois must be a list or removed */ }\n    }\n}","typeGuard":"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 }","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"persistent client at index\") { /* check client at that index, coerce whois to a list, retry */ }","preventionTips":["Keep whois/services fields as lists of strings"],"tags":["config","migration","client","whois","type-mismatch"],"backgroundTag":"config-field-type-mismatch","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}