{"record":{"id":"cd183b9813384baa","repo":"mem0ai/mem0","slug":"invalid-metadata-key-metadatakey-only-letter","errorCode":null,"errorMessage":"Invalid metadata key '${metadataKey}'. Only letters, numbers, underscores, nesting via '.', and array wildcards '[*]' are allowed.","messagePattern":"Invalid metadata key '(.+?)'\\. Only letters, numbers, underscores, nesting via '\\.', and array wildcards '\\[\\*\\]' are allowed\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mem0-ts/src/oss/src/vector_stores/oracledb.ts","lineNumber":58,"sourceCode":"  },\n};\n\nconst IDENTIFIER_RE = /^(?:\"[^\"]+\"|[^\".]+)(?:\\.(?:\"[^\"]+\"|[^\".]+))*$/;\nconst METADATA_KEY_RE = /^[a-zA-Z0-9_.[\\],\\s*]+$/;\n\nexport function quoteIdentifier(name: string): string {\n  const trimmed = name.trim();\n  if (!IDENTIFIER_RE.test(trimmed)) {\n    throw new Error(`Identifier name ${name} is not valid.`);\n  }\n  return [...trimmed.matchAll(/\"([^\"]+)\"|([^\".]+)/g)]\n    .map((m) => `\"${m[1] ?? m[2]}\"`)\n    .join(\".\");\n}\n\nfunction jsonPath(metadataKey: string): string {\n  if (!METADATA_KEY_RE.test(metadataKey)) {\n    throw new Error(\n      `Invalid metadata key '${metadataKey}'. Only letters, numbers, underscores, ` +\n        `nesting via '.', and array wildcards '[*]' are allowed.`,\n    );\n  }\n  return metadataKey\n    .split(\".\")\n    .map((part) =>\n      part.endsWith(\"[*]\") ? `.\"${part.slice(0, -3)}\"[*]` : `.\"${part}\"`,\n    )\n    .join(\"\");\n}\n\nconst COMPARISON_OPERATORS: Record<string, string> = {\n  eq: \"==\",\n  ne: \"!=\",\n  gt: \">\",\n  gte: \">=\",\n  lt: \"<\",","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/oss/src/vector_stores/oracledb.ts#L40-L76","documentation":"Metadata keys are embedded into Oracle JSON path expressions (JSON_EXISTS / JSON_VALUE with '$.path'). The METADATA_KEY_RE allow-list (letters, digits, underscore, dot, brackets, comma, whitespace, asterisk) prevents keys containing quotes, dollar signs, or other characters that would alter the path semantics or break out into SQL. Keys failing the pattern are rejected up front.","triggerScenarios":"Filtering or reading a metadata key like \"user's name\", 'cost$', 'a\"b', or keys with slashes/hashes: filters = { \"weird/key\": 'x' }.","commonSituations":"Free-form metadata keys derived from user profiles or document attributes; migrating metadata schemas from document DBs that allow any key; i18n keys with accented characters beyond [a-zA-Z].","solutions":["Sanitize metadata keys at write time to the allowed character set (letters, digits, underscore, dot, [*]).","Rename offending keys before querying: map 'user's name' -> 'user_name'.","Enforce a key pattern in your ingestion pipeline so only safe keys reach the store."],"exampleFix":"// before\nfilters = { \"user's name\": 'alice' };\n\n// after\n// store payload with sanitized key\nfilters = { user_name: 'alice' };","handlingStrategy":"validation","validationCode":"const KEY = /^[a-zA-Z0-9_.[\\],\\s*]+$/;\nfunction sanitizeKeys(payload: Record<string, any>): Record<string, any> {\n  const out: Record<string, any> = {};\n  for (const [k, v] of Object.entries(payload)) {\n    if (!KEY.test(k)) throw new TypeError(`Illegal metadata key: ${k}`);\n    out[k] = v;\n  }\n  return out;\n}","typeGuard":"const isSafeMetadataKey = (k: string): boolean => /^[a-zA-Z0-9_.[\\],\\s*]+$/.test(k);","tryCatchPattern":null,"preventionTips":["Enforce a metadata key pattern at ingestion","Sanitize free-form attribute names to snake_case","Reject keys containing quotes, $, or slashes early"],"tags":["oracledb","metadata","json-path","validation"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}