{"record":{"id":"9ebfd2dcb218fd84","repo":"mem0ai/mem0","slug":"identifier-name-name-is-not-valid","errorCode":null,"errorMessage":"Identifier name ${name} is not valid.","messagePattern":"Identifier name (.+?) is not valid\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mem0-ts/src/oss/src/vector_stores/oracledb.ts","lineNumber":49,"sourceCode":"> = {\n  HNSW: {\n    neighbors: [2, 2048],\n    efconstruction: [1, 65535],\n  },\n  IVF: {\n    \"neighbor partitions\": [1, 10_000_000],\n    samples_per_partition: [1, Number.MAX_SAFE_INTEGER],\n    min_vectors_per_partition: [0, Number.MAX_SAFE_INTEGER],\n  },\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    )","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/oss/src/vector_stores/oracledb.ts#L31-L67","documentation":"Oracle identifiers (table/index/column names) are quoted and interpolated into SQL by quoteIdentifier(). The regex allows dot-separated segments, optionally double-quoted, and nothing else. Names containing characters outside that grammar would break out of the quoted identifier or allow SQL injection, so invalid names are rejected before any SQL is built.","triggerScenarios":"Setting a table or index name containing characters like semicolons, quotes-with-nested-quotes, backticks, or stray whitespace patterns that fail IDENTIFIER_RE, e.g. config { tableName: 'memories; DROP TABLE x' }.","commonSituations":"Using unvalidated dynamic table names from tenant/user input; names copied from another database dialect with backticks (MySQL) or brackets (MSSQL); environment-specific naming with special characters.","solutions":["Use simple alphanumeric names with optional dots and double quotes: MEMORIES, scott.MEMORIES.","Never build table/index names from raw user input; map tenant IDs to a fixed allow-list of names.","Strip dialect-specific quoting (backticks, square brackets) from names migrated from MySQL/MSSQL."],"exampleFix":"// before\nnew OracleDB({ tableName: '`memories`' }); // MySQL-style backticks\n\n// after\nnew OracleDB({ tableName: 'memories' });","handlingStrategy":"type-guard","validationCode":"const IDENTIFIER = /^(?:\"[^\"]+\"|[^\".]+)(?:\\.(?:\"[^\"]+\"|[^\".]+))*$/;\nif (!IDENTIFIER.test(tableName.trim())) throw new TypeError(`Invalid Oracle identifier: ${tableName}`);","typeGuard":"const isValidOracleIdentifier = (name: string): boolean =>\n  /^(?:\"[^\"]+\"|[A-Za-z][A-Za-z0-9_$#]*)(?:\\.(?:\"[^\"]+\"|[A-Za-z][A-Za-z0-9_$#]*))*$/.test(name.trim());","tryCatchPattern":null,"preventionTips":["Use fixed alphanumeric table/index names from config, never user input","Map tenants to an allow-list of names","Strip MySQL/MSSQL quoting when migrating schemas"],"tags":["oracledb","sql-injection","identifier","validation"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}