mastra-ai/mastra · error · FactoryRuleValidationError

Rule metadata contains too many fields.

Error message

Rule metadata contains too many fields.

What it means

Each metadata object is also capped at 100 fields (entries), mirroring the array cap, so no single level of the metadata tree can fan out unboundedly. Oversized records should be summarized or restructured before reaching the decision validator.

Source

Thrown at mastracode/factory/src/rules/validation.ts:117

    if (!Number.isFinite(value)) throw new FactoryRuleValidationError('Rule metadata must contain finite numbers.');
    return value;
  }
  if (depth >= MAX_JSON_DEPTH || (typeof value !== 'object' && !Array.isArray(value))) {
    throw new FactoryRuleValidationError('Rule metadata is not bounded JSON.');
  }
  if (seen.has(value as object)) throw new FactoryRuleValidationError('Rule metadata must not contain cycles.');
  seen.add(value as object);
  try {
    if (Array.isArray(value)) {
      if (value.length > MAX_JSON_COLLECTION_SIZE) {
        throw new FactoryRuleValidationError('Rule metadata contains too many entries.');
      }
      return value.map(entry => normalizeFactoryRuleJsonValue(entry, depth + 1, seen));
    }
    if (!isPlainObject(value)) throw new FactoryRuleValidationError('Rule metadata must use plain objects.');
    const entries = Object.entries(value);
    if (entries.length > MAX_JSON_COLLECTION_SIZE) {
      throw new FactoryRuleValidationError('Rule metadata contains too many fields.');
    }
    const sanitized: Record<string, FactoryRuleJsonValue> = {};
    for (const [key, entry] of entries) {
      const normalizedKey = boundedString(key, 'Rule metadata key', 128, IDENTIFIER_RE);
      sanitized[normalizedKey] = SENSITIVE_KEY_RE.test(normalizedKey)
        ? '[REDACTED]'
        : normalizeFactoryRuleJsonValue(entry, depth + 1, seen);
    }
    return sanitized;
  } finally {
    seen.delete(value as object);
  }
}

function sanitizeMetadata(value: unknown): Record<string, FactoryRuleJsonValue> | undefined {
  if (value === undefined) return undefined;
  const sanitized = normalizeFactoryRuleJsonValue(value);
  if (!isPlainObject(sanitized)) throw new FactoryRuleValidationError('Rule metadata must be an object.');

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Cap the record: keep the first 100 entries and add a count of the rest.
  2. Aggregate into counts/summary stats instead of per-item keys.
  3. Use an array of {key, value} pairs if order matters and slice to 100.
  4. Persist the full map externally and store a URI or digest in metadata.

Example fix

// before
metadata: { resultsByTest: testMap } // 300 keys
// after
const entries = Object.entries(testMap).slice(0, 100);
metadata: { resultsByTest: Object.fromEntries(entries), totalTests: Object.keys(testMap).length }
Defensive patterns

Strategy: validation

Validate before calling

const capFields = (o: Record<string, unknown>, max = 100): Record<string, unknown> => {
  const entries = Object.entries(o);
  return entries.length > max ? Object.fromEntries(entries.slice(0, max)) : o;
};
metadata = { results: capFields(resultsByTest), totalResults: Object.keys(resultsByTest).length };

Type guard

const fitsFieldCap = (v: unknown): boolean =>
  !v || typeof v !== 'object' || Array.isArray(v) || Object.keys(v).length <= 100;

Try / catch

try {
  emit({ type: 'upsertLinkedWorkItem', metadata });
} catch (e) {
  if (e instanceof FactoryRuleValidationError && e.message.includes('too many fields')) {
    emit({ type: 'upsertLinkedWorkItem', metadata: summarizeLargeRecords(metadata) });
  } else throw e;
}

Prevention

When it happens

Trigger: Metadata where one object has more than 100 keys, e.g. a record keyed by filename, user id, or test name built from a large changeset or dataset.

Common situations: Building per-file or per-test result maps for large PRs, key-value accumulators grown over a long rule run, forwarding a large config/dictionary as metadata.

Related errors


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