{"record":{"id":"89e42f80fb4e17d7","repo":"mastra-ai/mastra","slug":"rule-metadata-contains-too-many-fields","errorCode":null,"errorMessage":"Rule metadata contains too many fields.","messagePattern":"Rule metadata contains too many fields\\.","errorType":"validation","errorClass":"FactoryRuleValidationError","httpStatus":null,"severity":"error","filePath":"mastracode/factory/src/rules/validation.ts","lineNumber":117,"sourceCode":"    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);\n  }\n}\n\nfunction sanitizeMetadata(value: unknown): Record<string, FactoryRuleJsonValue> | undefined {\n  if (value === undefined) return undefined;\n  const sanitized = normalizeFactoryRuleJsonValue(value);\n  if (!isPlainObject(sanitized)) throw new FactoryRuleValidationError('Rule metadata must be an object.');","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory/src/rules/validation.ts#L99-L135","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Cap the record: keep the first 100 entries and add a count of the rest.","Aggregate into counts/summary stats instead of per-item keys.","Use an array of {key, value} pairs if order matters and slice to 100.","Persist the full map externally and store a URI or digest in metadata."],"exampleFix":"// before\nmetadata: { resultsByTest: testMap } // 300 keys\n// after\nconst entries = Object.entries(testMap).slice(0, 100);\nmetadata: { resultsByTest: Object.fromEntries(entries), totalTests: Object.keys(testMap).length }","handlingStrategy":"validation","validationCode":"const capFields = (o: Record<string, unknown>, max = 100): Record<string, unknown> => {\n  const entries = Object.entries(o);\n  return entries.length > max ? Object.fromEntries(entries.slice(0, max)) : o;\n};\nmetadata = { results: capFields(resultsByTest), totalResults: Object.keys(resultsByTest).length };","typeGuard":"const fitsFieldCap = (v: unknown): boolean =>\n  !v || typeof v !== 'object' || Array.isArray(v) || Object.keys(v).length <= 100;","tryCatchPattern":"try {\n  emit({ type: 'upsertLinkedWorkItem', metadata });\n} catch (e) {\n  if (e instanceof FactoryRuleValidationError && e.message.includes('too many fields')) {\n    emit({ type: 'upsertLinkedWorkItem', metadata: summarizeLargeRecords(metadata) });\n  } else throw e;\n}","preventionTips":["Prefer aggregate counts over per-item keys for large datasets.","Cap any dynamically-keyed record at build time, storing totals separately.","Apply the cap at every object level, matching the per-level 100 limit.","Test rules with realistic large inputs, not toy datasets."],"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"}