{"record":{"id":"fc0e5c1506174faa","repo":"mastra-ai/mastra","slug":"invalid-metadata-filter-key-key","errorCode":null,"errorMessage":"Invalid metadata filter key \"${key}\".","messagePattern":"Invalid metadata filter key \"(.+?)\"\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/core/src/storage/utils.ts","lineNumber":116,"sourceCode":"const MAX_METADATA_KEY_LENGTH = 128;\nconst DISALLOWED_METADATA_KEYS = new Set(['__proto__', 'prototype', 'constructor']);\n\nexport function validateStorageMetadataFilter(\n  metadata: StorageMetadataFilter | undefined,\n): StorageMetadataFilter | undefined {\n  if (metadata === undefined) return undefined;\n  if (!metadata || typeof metadata !== 'object' || Array.isArray(metadata)) {\n    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,","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/storage/utils.ts#L98-L134","documentation":"Each key in a metadata filter must be a non-empty string up to MAX_METADATA_KEY_LENGTH, match SAFE_METADATA_KEY_PATTERN, and not be in the DISALLOWED_METADATA_KEYS set (reserved keys). Keys that are too long, contain unsafe characters, or collide with reserved names are rejected so filters remain safe and unambiguous across storage backends.","triggerScenarios":"Using a key longer than the max length, keys with special characters like '$', '.', spaces, or unicode outside the safe pattern, or reserved/disallowed keys (e.g. a key named like a storage field).","commonSituations":"Copying raw user input or URL fragments into metadata keys; using Mongo-style operators ('$gte', '$or') expecting rich queries; using dotted paths ('user.id') expecting nested matching.","solutions":["Shorten the key within the allowed max length","Use only safe identifier-like characters: letters, digits, underscore, hyphen (alphanumerics only to be safe)","Rename reserved/disallowed keys to a non-conflicting name (e.g. prefix 'meta_')","Sanitize user-supplied keys before use: replace disallowed chars, e.g. key.replace(/[^a-zA-Z0-9_-]/g, '_')"],"exampleFix":"// before\nmetadata: { 'user.profile.id': 42 }\n// after\nmetadata: { 'user-profile-id': 42 }","handlingStrategy":"validation","validationCode":"const SAFE_KEY = /^[a-zA-Z0-9_-]+$/;\nfunction isValidMetadataKey(k: string, maxLen = 64): boolean {\n  return k.length > 0 && k.length <= maxLen && SAFE_KEY.test(k);\n}\nconst clean = Object.fromEntries(\n  Object.entries(raw).map(([k, v]) => [k.replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 64), v])\n);","typeGuard":"function hasSafeKeys(f: Record<string, unknown>): boolean {\n  return Object.keys(f).every(k => /^[a-zA-Z0-9_-]+$/.test(k));\n}","tryCatchPattern":"try {\n  return await storage.listTraces({ metadata: filter });\n} catch (e) {\n  if (e instanceof TypeError && e.message.includes('metadata filter key')) {\n    const key = /key \"([^\"]+)\"/.exec(e.message)?.[1];\n    logger.warn('Invalid metadata key dropped', { key });\n    const { [key!]: _, ...rest } = filter;\n    return await storage.listTraces({ metadata: rest });\n  }\n  throw e;\n}","preventionTips":["Sanitize user-supplied keys to a safe alphabet before storing or filtering","Avoid MongoDB-style operator keys ($gt, $or) — equality-only semantics","Keep keys short; encode hierarchy in the value, not dotted keys","Document the allowed key charset for your team's metadata conventions"],"tags":["validation","storage","metadata"],"backgroundTag":"metadata-filter-key-invalid","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}