{"record":{"id":"8baa6b131df04375","repo":"mem0ai/mem0","slug":"invalid-label-name-only-letters-digits-8baa6b","errorCode":null,"errorMessage":"Invalid ${label} '${name}': only letters, digits, and underscores are allowed, must start with a letter or underscore, and be at most 128 characters.","messagePattern":"Invalid (.+?) '(.+?)': only letters, digits, and underscores are allowed, must start with a letter or underscore, and be at most 128 characters\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mem0-ts/src/oss/src/vector_stores/pgvector.ts","lineNumber":14,"sourceCode":"import type { Client as ClientType, ClientConfig } from \"pg\";\nimport pkg from \"pg\";\nconst { Client, escapeIdentifier } = pkg;\nimport { VectorStore } from \"./base\";\nimport { SearchFilters, VectorStoreConfig, VectorStoreResult } from \"../types\";\n\nconst SAFE_IDENTIFIER_RE = /^[a-zA-Z_][a-zA-Z0-9_]{0,127}$/;\n\nfunction validateIdentifier(\n  name: string,\n  label: string = \"identifier\",\n): string {\n  if (!SAFE_IDENTIFIER_RE.test(name)) {\n    throw new Error(\n      `Invalid ${label} '${name}': only letters, digits, and underscores are allowed, ` +\n        `must start with a letter or underscore, and be at most 128 characters.`,\n    );\n  }\n  return name;\n}\n\nfunction escapeFilterKey(key: string): string {\n  if (!SAFE_IDENTIFIER_RE.test(key)) {\n    throw new Error(\n      `Invalid filter key '${key}': only letters, digits, and underscores are allowed.`,\n    );\n  }\n  return key;\n}\n\ninterface FilterResult {\n  conditions: string[];","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/oss/src/vector_stores/pgvector.ts#L1-L32","documentation":"The pgvector vector store in mem0-ts validates every SQL identifier (collection/table names) against SAFE_IDENTIFIER_RE (/^[a-zA-Z_][a-zA-Z0-9_]{0,127}$/) before interpolating it into SQL. If the configured collectionName (or other identifier) contains characters outside letters/digits/underscores, does not start with a letter or underscore, or exceeds 128 characters, this error is thrown. It exists to prevent SQL injection through identifiers, since pg has no parameter binding for identifiers.","triggerScenarios":"Constructing PgVector with a collectionName containing a hyphen or dot (e.g. 'my-memories' or 'mem0.prod'), starting with a digit ('2mem'), containing spaces, being longer than 128 chars, or passing an empty/dynamic name built from user input (tenant IDs like 'user-123', emails like 'user@example.com').","commonSituations":"Migrating from another store where hyphenated index names were allowed; using tenant/user IDs or timestamps as collection names; copying a Postgres table name that was quoted at creation time; version upgrades that introduced this strict validation.","solutions":["Change the collection name to use only letters, digits, and underscores, e.g. 'my_memories' instead of 'my-memories'","If the name is derived from external input, sanitize it before passing: replace invalid characters with underscores and prefix with a letter if it starts with a digit","If you must keep a hyphenated/dotted table name in Postgres, rename the table to a compliant name (ALTER TABLE) or use a separate mapping layer","Verify the name length is at most 128 characters when generated dynamically (e.g. hashed/truncated tenant IDs)"],"exampleFix":"// before\nconst vs = new PgVector({ collectionName: 'user-123-memories', ... });\n\n// after\nconst vs = new PgVector({ collectionName: 'user_123_memories', ... });","handlingStrategy":"validation","validationCode":"const SAFE_IDENTIFIER_RE = /^[a-zA-Z_][a-zA-Z0-9_]{0,127}$/;\nfunction assertIdentifier(name: string, label = 'collectionName') {\n  if (!SAFE_IDENTIFIER_RE.test(name)) {\n    throw new Error(`${label} '${name}' must match [a-zA-Z_][a-zA-Z0-9_]{0,127}`);\n  }\n}\nassertIdentifier(config.collectionName);","typeGuard":"const isSafeIdentifier = (s: unknown): s is string =>\n  typeof s === 'string' && /^[a-zA-Z_][a-zA-Z0-9_]{0,127}$/.test(s);","tryCatchPattern":"try { const vs = new PgVector(config); } catch (e) { if (e instanceof Error && e.message.startsWith('Invalid ')) { /* fix name, do not retry */ } throw e; }","preventionTips":["Normalize all generated collection names to [a-zA-Z_][a-zA-Z0-9_]{0,127} at creation time","Never build identifiers from raw user input (emails, tenant IDs) without sanitization","Centralize collection-name generation in one helper used by every environment"],"tags":["pgvector","postgres","sql-injection","validation","configuration","typescript"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}