{"record":{"id":"3d940d60c347f56c","repo":"mastra-ai/mastra","slug":"invalid-filter-format-expected-a-plain-object-go","errorCode":null,"errorMessage":"Invalid filter format: expected a plain object, got ${receivedType}","messagePattern":"Invalid filter format: expected a plain object, got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/rag/src/utils/tool-helpers.ts","lineNumber":195,"sourceCode":"  let parsedFilter = filter;\n  if (typeof filter === 'string') {\n    try {\n      parsedFilter = JSON.parse(filter);\n    } catch (error) {\n      if (logger) {\n        logger.error('Invalid filter', { filter, error });\n      }\n      throw new Error(`Invalid filter format: ${error instanceof Error ? error.message : String(error)}`);\n    }\n  }\n\n  // Validate that non-string filter is a plain object\n  if (typeof parsedFilter !== 'object' || parsedFilter === null || Array.isArray(parsedFilter)) {\n    const receivedType = Array.isArray(parsedFilter) ? 'array' : typeof parsedFilter;\n    if (logger) {\n      logger.error('Invalid filter', { filter, error: 'Filter must be a plain object' });\n    }\n    throw new Error(`Invalid filter format: expected a plain object, got ${receivedType}`);\n  }\n\n  return parsedFilter as Record<string, any>;\n}\n","sourceCodeStart":177,"sourceCodeEnd":200,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/rag/src/utils/tool-helpers.ts#L177-L200","documentation":"After parsing (or if the input was already an object), parseFilterValue validates that the resulting filter is a plain object — not null, an array, or a primitive. This error is thrown when the filter resolves to a non-plain-object value, because vector-store metadata filters must be an object of field conditions.","triggerScenarios":"Passing `filter` as an array (e.g. `[\"a\",\"b\"]` or `[{...}]`), a JSON string like `\"null\"`, `\"[...]\"` or `\"42\"`, or a value like a number/boolean that parsed successfully but is not an object.","commonSituations":"LLM tool calls emitting JSON arrays as filters; users passing list-style conditions expecting OR semantics; configs where a filter variable was accidentally set to null/undefined-as-string.","solutions":["Wrap conditions in an object, e.g. `{ category: { $in: ['a','b'] } }` instead of an array.","Ensure string filters parse to a JSON object, not an array or scalar.","Guard the call site: check the value is a non-null non-array object before invoking the tool.","Translate list-style intent into the vector store's supported operators ($in/$or)."],"exampleFix":"// before\nawait tool.execute({ filter: [\"news\", \"sports\"] });\n// after\nawait tool.execute({ filter: { category: { $in: [\"news\", \"sports\"] } } });","handlingStrategy":"validation","validationCode":"function isPlainObject(v: unknown): v is Record<string, unknown> {\n  return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\nif (!isPlainObject(filter)) throw new TypeError('filter must be a plain object of field conditions');","typeGuard":"function isPlainObject(v: unknown): v is Record<string, unknown> {\n  return Object.prototype.toString.call(v) === '[object Object]';\n}","tryCatchPattern":"try {\n  await tool.execute({ filter });\n} catch (e) {\n  if ((e as Error).message.includes('expected a plain object')) {\n    return tool.execute({ filter: normalizeFilter(filter) }); // wrap arrays via $in, drop null\n  }\n  throw e;\n}","preventionTips":["Express list conditions with $in/$or objects, never arrays.","Type the filter parameter as Record<string, unknown> so TS rejects arrays/scalars.","Normalize incoming (LLM-supplied) filters through a shape validator before execution."],"tags":["validation","filter","rag"],"backgroundTag":"invalid-filter-format","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}