mastra-ai/mastra · error · TypeError
Invalid metadata filter key "${key}".
Error message
Invalid metadata filter key "${key}". What it means
Each key in a metadata filter must be a non-empty string up to MAX_METADATA_KEY_LENGTH, match SAFE_METADATA_KEY_PATTERN, and not be in the DISALLOWED_METADATA_KEYS set (reserved keys). Keys that are too long, contain unsafe characters, or collide with reserved names are rejected so filters remain safe and unambiguous across storage backends.
Source
Thrown at packages/core/src/storage/utils.ts:116
const MAX_METADATA_KEY_LENGTH = 128;
const DISALLOWED_METADATA_KEYS = new Set(['__proto__', 'prototype', 'constructor']);
export function validateStorageMetadataFilter(
metadata: StorageMetadataFilter | undefined,
): StorageMetadataFilter | undefined {
if (metadata === undefined) return undefined;
if (!metadata || typeof metadata !== 'object' || Array.isArray(metadata)) {
throw new TypeError('Metadata filter must be an object.');
}
const entries = Object.entries(metadata);
for (const [key, value] of entries) {
if (
key.length > MAX_METADATA_KEY_LENGTH ||
!SAFE_METADATA_KEY_PATTERN.test(key) ||
DISALLOWED_METADATA_KEYS.has(key)
) {
throw new TypeError(`Invalid metadata filter key "${key}".`);
}
if (
value !== null &&
typeof value !== 'string' &&
typeof value !== 'boolean' &&
!(typeof value === 'number' && Number.isFinite(value))
) {
throw new TypeError(
`Invalid metadata filter value for key "${key}". Values must be string, finite number, boolean, or null.`,
);
}
}
return entries.length > 0 ? metadata : undefined;
}
export function storageMessageMatchesMetadataFilter(
content: unknown,View on GitHub (pinned to 75dd419e61)
Solutions
- Shorten the key within the allowed max length
- Use only safe identifier-like characters: letters, digits, underscore, hyphen (alphanumerics only to be safe)
- Rename reserved/disallowed keys to a non-conflicting name (e.g. prefix 'meta_')
- Sanitize user-supplied keys before use: replace disallowed chars, e.g. key.replace(/[^a-zA-Z0-9_-]/g, '_')
Example fix
// before
metadata: { 'user.profile.id': 42 }
// after
metadata: { 'user-profile-id': 42 } Defensive patterns
Strategy: validation
Validate before calling
const SAFE_KEY = /^[a-zA-Z0-9_-]+$/;
function isValidMetadataKey(k: string, maxLen = 64): boolean {
return k.length > 0 && k.length <= maxLen && SAFE_KEY.test(k);
}
const clean = Object.fromEntries(
Object.entries(raw).map(([k, v]) => [k.replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 64), v])
); Type guard
function hasSafeKeys(f: Record<string, unknown>): boolean {
return Object.keys(f).every(k => /^[a-zA-Z0-9_-]+$/.test(k));
} Try / catch
try {
return await storage.listTraces({ metadata: filter });
} catch (e) {
if (e instanceof TypeError && e.message.includes('metadata filter key')) {
const key = /key "([^"]+)"/.exec(e.message)?.[1];
logger.warn('Invalid metadata key dropped', { key });
const { [key!]: _, ...rest } = filter;
return await storage.listTraces({ metadata: rest });
}
throw e;
} Prevention
- Sanitize user-supplied keys to a safe alphabet before storing or filtering
- Avoid MongoDB-style operator keys ($gt, $or) — equality-only semantics
- Keep keys short; encode hierarchy in the value, not dotted keys
- Document the allowed key charset for your team's metadata conventions
When it happens
Trigger: Using a key longer than the max length, keys with special characters like '$', '.', spaces, or unicode outside the safe pattern, or reserved/disallowed keys (e.g. a key named like a storage field).
Common situations: Copying raw user input or URL fragments into metadata keys; using Mongo-style operators ('$gte', '$or') expecting rich queries; using dotted paths ('user.id') expecting nested matching.
Related errors
- Invalid metadata key: "${key}".
- Invalid metadata key: "${key}". Keys must start with a lette
- Metadata key "${key}" exceeds maximum length of ${MAX_METADA
- Metadata filter must be an object.
- 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/fc0e5c1506174faa.
Report an issue: GitHub.