mem0ai/mem0 · error · Error

Invalid ${label} '${name}': only letters, digits, and unders

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.

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)

Solutions

  1. Change the collection name to use only letters, digits, and underscores, e.g. 'my_memories' instead of 'my-memories'
  2. 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
  3. 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
  4. 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

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


AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15). Data as JSON: /api/errors/8baa6b131df04375. Report an issue: GitHub.