mastra-ai/mastra · error
Invalid metadata key: "${key}". Keys must start with a lette
Error message
Invalid metadata key: "${key}". Keys must start with a letter or underscore and contain only alphanumeric characters and underscores. What it means
Mastra storage validates thread metadata keys before persisting or listing threads. A key is rejected if it contains characters other than letters, digits, and underscores, or if it starts with a non-letter/non-underscore character. This guard prevents keys that could break storage backends, query syntax, or serialization.
Source
Thrown at packages/core/src/storage/domains/memory/base.ts:434
/**
* Validates metadata keys to prevent SQL injection attacks and prototype pollution.
* Keys must start with a letter or underscore, followed by alphanumeric characters or underscores.
* @param metadata - The metadata object to validate
* @throws Error if any key contains invalid characters or is a disallowed key
*/
protected validateMetadataKeys(metadata: Record<string, unknown> | undefined): void {
if (!metadata) return;
for (const key of Object.keys(metadata)) {
// First check for disallowed prototype pollution keys
if (DISALLOWED_METADATA_KEYS.has(key)) {
throw new Error(`Invalid metadata key: "${key}".`);
}
// Then check pattern
if (!SAFE_METADATA_KEY_PATTERN.test(key)) {
throw new Error(
`Invalid metadata key: "${key}". Keys must start with a letter or underscore and contain only alphanumeric characters and underscores.`,
);
}
// Also limit key length to prevent potential issues
if (key.length > MAX_METADATA_KEY_LENGTH) {
throw new Error(`Metadata key "${key}" exceeds maximum length of ${MAX_METADATA_KEY_LENGTH} characters.`);
}
}
}
/**
* Validates pagination parameters and returns safe offset.
* @param page - Page number (0-indexed)
* @param perPage - Items per page (0 is allowed and returns empty results)
* @throws Error if page is negative, perPage is negative/invalid, or offset would overflow
*/
protected validatePagination(page: number, perPage: number): void {View on GitHub (pinned to 75dd419e61)
Solutions
- Rename the offending metadata key to match /^[A-Za-z_][A-Za-z0-9_]*$/ (e.g. 'my-key' -> 'my_key').
- Sanitize keys programmatically before writing metadata: replace invalid characters with underscores.
- Drop or move invalid keys into a nested value instead of the key itself.
- Wrap listThreads/saveThread calls in try-catch and log/repair the offending thread data.
Example fix
// before
await memory.storage.listThreads({ metadata: { 'user-id': '42' } });
// after
await memory.storage.listThreads({ metadata: { 'user_id': '42' } }); Defensive patterns
Strategy: validation
Validate before calling
const SAFE_KEY = /^[A-Za-z_][A-Za-z0-9_]*$/;
function assertValidMetadataKeys(metadata) {
for (const key of Object.keys(metadata ?? {})) {
if (!SAFE_KEY.test(key)) throw new Error(`Invalid metadata key: "${key}"`);
}
} Type guard
function hasSafeMetadataKeys(m: unknown): m is Record<string, unknown> {
return !!m && Object.keys(m).every(k => /^[A-Za-z_][A-Za-z0-9_]*$/.test(k));
} Try / catch
try {
await storage.listThreads(params);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Invalid metadata key')) {
// sanitize metadata and retry
} else throw e;
} Prevention
- Sanitize keys on write (replace invalid chars with _), never on read
- Never use raw user input as metadata keys
- Keep metadata keys as fixed literal strings in code
When it happens
Trigger: Calling listThreads (or any code path that invokes validateMetadataKeys) with a thread whose metadata record contains a key like 'my-key', '123abc', 'foo.bar', or an empty string.
Common situations: Migrating data from another system that allowed hyphenated or dotted metadata keys; letting user input become metadata keys; generating keys from timestamps or IDs containing dashes or slashes.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Invalid metadata key: "${key}".
- Metadata key "${key}" exceeds maximum length of ${MAX_METADA
- Metadata filter must be an object.
- Invalid metadata filter key "${key}".
- Invalid metadata filter value for key "${key}". Values must
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/f653d5bee165b816.
Report an issue: GitHub.