{"record":{"id":"1aa1bb6a37551277","repo":"mastra-ai/mastra","slug":"rule-metadata-contains-too-many-entries","errorCode":null,"errorMessage":"Rule metadata contains too many entries.","messagePattern":"Rule metadata contains too many entries\\.","errorType":"validation","errorClass":"FactoryRuleValidationError","httpStatus":null,"severity":"error","filePath":"mastracode/factory/src/rules/validation.ts","lineNumber":110,"sourceCode":"export function normalizeFactoryRuleJsonValue(\n  value: unknown,\n  depth = 0,\n  seen = new Set<object>(),\n): FactoryRuleJsonValue {\n  if (value === null || typeof value === 'boolean' || typeof value === 'string') return value;\n  if (typeof value === 'number') {\n    if (!Number.isFinite(value)) throw new FactoryRuleValidationError('Rule metadata must contain finite numbers.');\n    return value;\n  }\n  if (depth >= MAX_JSON_DEPTH || (typeof value !== 'object' && !Array.isArray(value))) {\n    throw new FactoryRuleValidationError('Rule metadata is not bounded JSON.');\n  }\n  if (seen.has(value as object)) throw new FactoryRuleValidationError('Rule metadata must not contain cycles.');\n  seen.add(value as object);\n  try {\n    if (Array.isArray(value)) {\n      if (value.length > MAX_JSON_COLLECTION_SIZE) {\n        throw new FactoryRuleValidationError('Rule metadata contains too many entries.');\n      }\n      return value.map(entry => normalizeFactoryRuleJsonValue(entry, depth + 1, seen));\n    }\n    if (!isPlainObject(value)) throw new FactoryRuleValidationError('Rule metadata must use plain objects.');\n    const entries = Object.entries(value);\n    if (entries.length > MAX_JSON_COLLECTION_SIZE) {\n      throw new FactoryRuleValidationError('Rule metadata contains too many fields.');\n    }\n    const sanitized: Record<string, FactoryRuleJsonValue> = {};\n    for (const [key, entry] of entries) {\n      const normalizedKey = boundedString(key, 'Rule metadata key', 128, IDENTIFIER_RE);\n      sanitized[normalizedKey] = SENSITIVE_KEY_RE.test(normalizedKey)\n        ? '[REDACTED]'\n        : normalizeFactoryRuleJsonValue(entry, depth + 1, seen);\n    }\n    return sanitized;\n  } finally {\n    seen.delete(value as object);","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory/src/rules/validation.ts#L92-L128","documentation":"Each array inside rule metadata is capped at MAX_JSON_COLLECTION_SIZE (100) entries. Arrays longer than that are rejected so a single metadata blob cannot grow unbounded; the sanitized result must stay compact since total metadata is also capped at 16 KiB of JSON.","triggerScenarios":"Passing metadata with an array of more than 100 items, e.g. a list of all changed files, all test results, or all log lines collected by the rule into an upsertLinkedWorkItem decision's metadata field.","commonSituations":"Logging large batch results (files, commits, test cases) into metadata, aggregating events over a long run, or forwarding an API response array directly into metadata.","solutions":["Slice the array to 100 items: arr.slice(0, 100).","Store a summary instead: counts, first N items, or a compact hash/digest string.","Move bulk data to an external store (file, artifact) and put a reference URL in metadata.","Chunk the data across multiple work-item updates if all entries are required."],"exampleFix":"// before\nmetadata: { files: allChangedFiles } // 500 entries\n// after\nmetadata: { files: allChangedFiles.slice(0, 100), totalFiles: allChangedFiles.length }","handlingStrategy":"validation","validationCode":"const capArray = (a: unknown[], max = 100) => a.length > max ? a.slice(0, max) : a;\nmetadata = { ...metadata, files: capArray(files), totalFiles: files.length };","typeGuard":"const fitsCollectionCap = (v: unknown): boolean =>\n  !Array.isArray(v) || v.length <= 100;","tryCatchPattern":"try {\n  emit({ type: 'upsertLinkedWorkItem', metadata });\n} catch (e) {\n  if (e instanceof FactoryRuleValidationError && e.message.includes('too many entries')) {\n    emit({ type: 'upsertLinkedWorkItem', metadata: truncateArrays(metadata, 100) });\n  } else throw e;\n}","preventionTips":["Slice large arrays and record the total in a separate count field.","Store bulk data externally and reference it by URL/digest in metadata.","Remember the cap applies per array at every nesting level, not just top level.","Add a size assertion in your rule tests: expect(arraysIn(metadata).every(a => a.length <= 100)).toBe(true)."],"tags":["validation","limits","json"],"backgroundTag":"payload-too-large","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}