mastra-ai/mastra · error

Invalid ${kind}: ${name}. Must start with a letter or unders

Error message

Invalid ${kind}: ${name}. Must start with a letter or underscore, contain only letters, numbers, or underscores, and be at most 63 characters long.

What it means

`parseSqlIdentifier` validates SQL table/column/index names against `SQL_IDENTIFIER_PATTERN` (start with letter or underscore, only letters/numbers/underscores) and a 63-character limit (PostgreSQL identifier max). It throws this error to prevent SQL injection and to surface names that would be truncated or require quoting by the storage layer.

Source

Thrown at packages/core/src/utils.ts:595

/**
 * Parses and returns a valid SQL identifier (such as a table or column name).
 * The identifier must:
 *   - Start with a letter (a-z, A-Z) or underscore (_)
 *   - Contain only letters, numbers, or underscores
 *   - Be at most 63 characters long
 *
 * @param name - The identifier string to parse.
 * @param kind - Optional label for error messages (e.g., 'table name').
 * @returns The validated identifier as a branded type.
 * @throws {Error} If the identifier does not conform to SQL naming rules.
 *
 * @example
 * const id = parseSqlIdentifier('my_table'); // Ok
 * parseSqlIdentifier('123table'); // Throws error
 */
export function parseSqlIdentifier(name: string, kind = 'identifier'): SqlIdentifier {
  if (!SQL_IDENTIFIER_PATTERN.test(name) || name.length > 63) {
    throw new Error(
      `Invalid ${kind}: ${name}. Must start with a letter or underscore, contain only letters, numbers, or underscores, and be at most 63 characters long.`,
    );
  }
  return name as SqlIdentifier;
}

/**
 * Parses and returns a valid dot-separated SQL field key (e.g., 'user.profile.name').
 * Each segment must:
 *   - Start with a letter (a-z, A-Z) or underscore (_)
 *   - Contain only letters, numbers, or underscores
 *   - Be at most 63 characters long
 *
 * @param key - The dot-separated field key string to parse.
 * @returns The validated field key as a branded type.
 * @throws {Error} If any segment of the key is invalid.
 *
 * @example

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Rename the identifier to match `[A-Za-z_][A-Za-z0-9_]{0,62}` — replace dashes/dots/spaces with underscores.
  2. Truncate or hash long names to stay under 63 characters (e.g. prefix + short hash).
  3. Sanitize dynamic names before calling the API: `name.replace(/[^A-Za-z0-9_]/g, '_')` and assert length.
  4. Use Mastra's configuration options (e.g. table name prefixes) that produce compliant names instead of raw user input.

Example fix

// before
const table = `mastra-${tenantSlug}_traces`; // dashes from slug
// after
const table = `mastra_${tenantSlug.replace(/[^A-Za-z0-9_]/g, '_')}_traces`;
Defensive patterns

Strategy: validation

Validate before calling

const SQL_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
function assertSqlIdentifier(name: string, kind = 'identifier') {
  if (!SQL_IDENTIFIER_PATTERN.test(name) || name.length > 63)
    throw new Error(`Invalid ${kind}: ${name}`);
}

Type guard

function isSqlIdentifier(name: string): name is `${string}` {
  return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name) && name.length <= 63;
}

Try / catch

let table: SqlIdentifier;
try {
  table = parseSqlIdentifier(rawTableName, 'table');
} catch (e) {
  throw new Error(`Configured table name "${rawTableName}" is invalid: ${(e as Error).message}`);
}

Prevention

When it happens

Trigger: Passing a table name, column name, conflict column, or index name to a storage/DB adapter API (e.g. `parsedTableName`, `parsedColumn`, `parsedIndexName` callers) containing hyphens, dots, spaces, unicode, quotes, or a name longer than 63 chars; dynamic table names derived from user input or environment values like a prefixed `MASTRA_*` scope.

Common situations: Naming storage tables after tenant/product slugs with dashes (`my-app_agents`); auto-generating index names that exceed 63 chars due to long prefixes; interpolated table names from env vars containing invalid characters.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/1d71bc1c8356a8cf. Report an issue: GitHub.