mem0ai/mem0 · error · Error
Invalid ' ': only letters, digits, and underscores are…
Error message
Invalid ${label} '${name}': only letters, digits, and underscores are allowed, must start with a letter or underscore, and be at most 128 characters. What it means
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.
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)
Example fix
// before
const vs = new PgVector({ collectionName: 'user-123-memories', ... });
// after
const vs = new PgVector({ collectionName: 'user_123_memories', ... }); Defensive patterns
Strategy: validation
Validate before calling
const SAFE_IDENTIFIER_RE = /^[a-zA-Z_][a-zA-Z0-9_]{0,127}$/;
function assertIdentifier(name: string, label = 'collectionName') {
if (!SAFE_IDENTIFIER_RE.test(name)) {
throw new Error(`${label} '${name}' must match [a-zA-Z_][a-zA-Z0-9_]{0,127}`);
}
}
assertIdentifier(config.collectionName); Type guard
const isSafeIdentifier = (s: unknown): s is string =>
typeof s === 'string' && /^[a-zA-Z_][a-zA-Z0-9_]{0,127}$/.test(s); Try / catch
try { const vs = new PgVector(config); } catch (e) { if (e instanceof Error && e.message.startsWith('Invalid ')) { /* fix name, do not retry */ } throw e; } Prevention
- 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
When it happens
Trigger: 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').
Common situations: 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.
Related errors
- Invalid filter key ' ': only letters, digits, and…
- Invalid ' ': only letters, digits, and underscores are…
- Invalid ' ': only letters, digits, and underscores are…
- PGVector requires either connectionString or
- Databricks vector store: topK must be a positive integer…
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/8baa6b131df04375.
Report an issue: GitHub.
Appendix: source
Thrown at mem0-ts/src/oss/src/vector_stores/pgvector.ts:14
import type { Client as ClientType, ClientConfig } from "pg";
import pkg from "pg";
const { Client, escapeIdentifier } = pkg;
import { VectorStore } from "./base";
import { SearchFilters, VectorStoreConfig, VectorStoreResult } from "../types";
const SAFE_IDENTIFIER_RE = /^[a-zA-Z_][a-zA-Z0-9_]{0,127}$/;
function validateIdentifier(
name: string,
label: string = "identifier",
): string {
if (!SAFE_IDENTIFIER_RE.test(name)) {
throw new Error(
`Invalid ${label} '${name}': only letters, digits, and underscores are allowed, ` +
`must start with a letter or underscore, and be at most 128 characters.`,
);
}
return name;
}
function escapeFilterKey(key: string): string {
if (!SAFE_IDENTIFIER_RE.test(key)) {
throw new Error(
`Invalid filter key '${key}': only letters, digits, and underscores are allowed.`,
);
}
return key;
}
interface FilterResult {
conditions: string[];View on GitHub (pinned to 001c235229)