{"record":{"id":"eabd13683f9f086f","repo":"mastra-ai/mastra","slug":"invalid-metadata-filter-value-for-key-key-va","errorCode":null,"errorMessage":"Invalid metadata filter value for key \"${key}\". Values must be string, finite number, boolean, or null.","messagePattern":"Invalid metadata filter value for key \"(.+?)\"\\. Values must be string, finite number, boolean, or null\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/core/src/storage/utils.ts","lineNumber":124,"sourceCode":"    throw new TypeError('Metadata filter must be an object.');\n  }\n\n  const entries = Object.entries(metadata);\n  for (const [key, value] of entries) {\n    if (\n      key.length > MAX_METADATA_KEY_LENGTH ||\n      !SAFE_METADATA_KEY_PATTERN.test(key) ||\n      DISALLOWED_METADATA_KEYS.has(key)\n    ) {\n      throw new TypeError(`Invalid metadata filter key \"${key}\".`);\n    }\n    if (\n      value !== null &&\n      typeof value !== 'string' &&\n      typeof value !== 'boolean' &&\n      !(typeof value === 'number' && Number.isFinite(value))\n    ) {\n      throw new TypeError(\n        `Invalid metadata filter value for key \"${key}\". Values must be string, finite number, boolean, or null.`,\n      );\n    }\n  }\n\n  return entries.length > 0 ? metadata : undefined;\n}\n\nexport function storageMessageMatchesMetadataFilter(\n  content: unknown,\n  filter: StorageMetadataFilter | undefined,\n): boolean {\n  if (!filter) return true;\n  const parsedContent = typeof content === 'string' ? safelyParseJSON(content) : content;\n  if (!parsedContent || typeof parsedContent !== 'object' || Array.isArray(parsedContent)) return false;\n  const metadata = (parsedContent as { metadata?: unknown }).metadata;\n  if (!metadata || typeof metadata !== 'object' || Array.isArray(metadata)) return false;\n","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/storage/utils.ts#L106-L142","documentation":"Metadata filter values must be string, boolean, finite number, or null. Objects, arrays, undefined, NaN, and Infinity are rejected because storage metadata matching supports only scalar equality semantics.","triggerScenarios":"Passing nested objects ({ nested: { a: 1 } }), arrays ({ tags: ['a','b'] }), undefined, NaN, or Infinity as a value for some key in the metadata filter object.","commonSituations":"Expecting array 'IN' semantics (values: [..]) or range objects ({$gt: 5}); passing raw Date objects; NaN leaking from computed values.","solutions":["Use a scalar value: string, boolean, finite number, or null","For multiple candidate values, issue multiple queries or encode as a delimited string ('a|b')","Convert Dates to ISO strings: date.toISOString()","Check finiteness: Number.isFinite(value) before building the filter"],"exampleFix":"// before\nmetadata: { createdAt: new Date(), tags: ['a','b'] }\n// after\nmetadata: { createdAt: new Date().toISOString(), tag: 'a' }","handlingStrategy":"validation","validationCode":"function isValidMetadataValue(v: unknown): boolean {\n  return v === null || typeof v === 'string' || typeof v === 'boolean' ||\n    (typeof v === 'number' && Number.isFinite(v));\n}\nif (!Object.values(filter).every(isValidMetadataValue)) throw new Error('Bad metadata values');","typeGuard":"type MetadataValue = string | number | boolean | null;\nfunction isMetadataValue(v: unknown): v is MetadataValue {\n  return v === null || typeof v === 'string' || typeof v === 'boolean' ||\n    (typeof v === 'number' && Number.isFinite(v));\n}","tryCatchPattern":"try {\n  return await storage.listTraces({ metadata: filter });\n} catch (e) {\n  if (e instanceof TypeError && e.message.includes('metadata filter value')) {\n    logger.warn('Falling back to unfiltered query', { filter });\n    return await storage.listTraces({});\n  }\n  throw e;\n}","preventionTips":["Serialize Dates/objects to strings before adding to metadata","Guard against NaN/Infinity with Number.isFinite","Use separate queries instead of array values for 'IN' semantics","Type metadata maps as Record<string, MetadataValue> so TS catches bad values"],"tags":["validation","storage","metadata"],"backgroundTag":"metadata-filter-value-invalid","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}