{"record":{"id":"c5ed81117aae6861","repo":"pocketbase/pocketbase","slug":"expected-map-or-array-got-v","errorCode":null,"errorMessage":"expected map or array, got %#v","messagePattern":"expected map or array, got %#v","errorType":"exception","errorClass":null,"httpStatus":400,"severity":"error","filePath":"core/record_field_resolver.go","lineNumber":540,"sourceCode":"\t\treturn arrVal(m, keys...)\n\tcase []uint16:\n\t\treturn arrVal(m, keys...)\n\tcase []uint32:\n\t\treturn arrVal(m, keys...)\n\tcase []uint64:\n\t\treturn arrVal(m, keys...)\n\tcase []mapExtractor:\n\t\textracted := make([]any, len(m))\n\t\tfor i, v := range m {\n\t\t\textracted[i] = v.AsMap()\n\t\t}\n\t\treturn arrVal(extracted, keys...)\n\tcase []any:\n\t\treturn arrVal(m, keys...)\n\tcase []types.JSONRaw:\n\t\treturn arrVal(m, keys...)\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"expected map or array, got %#v\", rawData)\n\t}\n}\n\nfunc mapVal[T any](m map[string]T, keys ...string) (any, error) {\n\tresult, ok := m[keys[0]]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"invalid key path - missing key %q\", keys[0])\n\t}\n\n\t// end key reached\n\tif len(keys) == 1 {\n\t\treturn result, nil\n\t}\n\n\treturn extractNestedVal(result, keys[1:]...)\n}\n\nfunc arrVal[T any](m []T, keys ...string) (any, error) {","sourceCodeStart":522,"sourceCodeEnd":558,"githubUrl":"https://github.com/pocketbase/pocketbase/blob/5d217ddb50cb144d80a5d0b0bdf11b52b2c3e457/core/record_field_resolver.go#L522-L558","documentation":"extractNestedVal walked a key path into a JSON value whose current node is neither a map nor an array (e.g. a string or number), so the remaining path segments cannot be applied. The message prints the offending value with %#v, showing exactly what was found instead.","triggerScenarios":"Filter like \"meta.tags.name = 'x'\" where meta.tags is a plain string in some rows (not an array of objects), or \"settings.theme.dark = true\" where settings.theme is the boolean true.","commonSituations":"Heterogeneous json field content across rows (some rows store a scalar where others store an object); schema evolved inside a schemaless json field; filter authored against an example row that is not representative.","solutions":["Inspect the printed value — it tells you the actual type at that path; adjust the filter path to match the real structure.","Normalize the stored data so the path has a consistent shape in every row (migration over the json column).","Guard heterogeneous fields by first filtering on a stable part (e.g. type discriminator) before the nested path."],"exampleFix":"// before: tags sometimes stored as string\nfilter := \"meta.tags.name = 'x'\"\n// after: normalize data so tags is always an array of objects, then keep the filter","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isMapOrArray(v any) bool {\n    switch v.(type) {\n    case map[string]any, []any:\n        return true\n    }\n    return false\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"expected map or array\") {\n    // the %#v in the message shows the actual value — align the filter path with the real shape\n}","preventionTips":["Keep json field shapes uniform across rows (schema discipline inside json).","Test filters against a representative sample of rows, not one record.","Prefer typed top-level fields for anything you filter on regularly."],"tags":["json","filter","data-quality"],"backgroundTag":null,"analyzedSha":"5d217ddb50cb144d80a5d0b0bdf11b52b2c3e457","analyzedAt":"2026-08-15T10:06:33.165Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}