{"record":{"id":"d813deba3e525c8c","repo":"mastra-ai/mastra","slug":"label-must-be-an-object","errorCode":null,"errorMessage":"${label} must be an object.","messagePattern":"(.+?) must be an object\\.","errorType":"validation","errorClass":"FactoryRuleValidationError","httpStatus":null,"severity":"error","filePath":"mastracode/factory/src/rules/validation.ts","lineNumber":143,"sourceCode":"    }\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.');\n  if (JSON.stringify(sanitized).length > MAX_METADATA_JSON_LENGTH) {\n    throw new FactoryRuleValidationError('Rule metadata is too large.');\n  }\n  return sanitized;\n}\n\nfunction validateBoardRules(rules: unknown, label: string): asserts rules is FactoryBoardRules {\n  if (!isPlainObject(rules)) throw new FactoryRuleValidationError(`${label} must be an object.`);\n  for (const [stage, sources] of Object.entries(rules)) {\n    enumValue(stage, FACTORY_RULE_STAGES, `${label} stage`);\n    if (!isPlainObject(sources)) throw new FactoryRuleValidationError(`${label}.${stage} must be an object.`);\n    for (const [source, leaf] of Object.entries(sources)) {\n      enumValue(source, FACTORY_RULE_SOURCES, `${label}.${stage} source`);\n      if (!isPlainObject(leaf)) throw new FactoryRuleValidationError(`${label}.${stage}.${source} must be an object.`);\n      assertExactKeys(leaf, ['onEnter', 'onExit'], `${label}.${stage}.${source}`);\n      for (const handler of Object.values(leaf)) {\n        if (handler !== undefined && typeof handler !== 'function') {\n          throw new FactoryRuleValidationError(`${label}.${stage}.${source} handlers must be functions.`);\n        }\n      }\n    }\n  }\n}\n\nexport function assertFactoryRules(rules: unknown): asserts rules is FactoryRules {\n  if (!isPlainObject(rules)) throw new FactoryRuleValidationError('Factory rules must be an object.');","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory/src/rules/validation.ts#L125-L161","documentation":"validateBoardRules asserts each rule board (work/review) is a plain object mapping stages to sources. If the whole board value passed via assertFactoryRules is not a plain object (null, array, class instance, primitive), this error names the failing board via the label argument.","triggerScenarios":"Calling assertFactoryRules / prepare / defaultFactoryRules with rules where rules.work or rules.review is null, an array, a Map/class instance, a string, or missing-but-explicitly-non-object (e.g. set to false).","commonSituations":"Hand-written rules config where work: null as a placeholder; JSON parsed from a config file where a board was omitted and defaulted to null; assigning an array of rules by mistake.","solutions":["Set the board to an object keyed by valid stage names, e.g. { plan: {} }.","If a board is unused, pass an empty object {} instead of null.","Check whether config deserialization (e.g. JSON.parse) produced null for missing keys and default it: rules.work ?? {}."],"exampleFix":"// before\nconst rules = { version: '1', work: null, review: {}, tools: {}, github: {}, linear: {} };\n// after\nconst rules = { version: '1', work: {}, review: {}, tools: {}, github: {}, linear: {} };","handlingStrategy":"validation","validationCode":"function isBoardRules(v) {\n  return v !== null && typeof v === 'object' && !Array.isArray(v);\n}\nif (!isBoardRules(rules.work) || !isBoardRules(rules.review)) {\n  throw new Error('rules.work and rules.review must be plain objects (use {} if empty)');\n}","typeGuard":"const isPlainRecord = (v: unknown): v is Record<string, unknown> =>\n  typeof v === 'object' && v !== null && !Array.isArray(v) &&\n  (Object.getPrototypeOf(v) === Object.prototype || Object.getPrototypeOf(v) === null);","tryCatchPattern":"try {\n  assertFactoryRules(rules);\n} catch (e) {\n  if (e.name === 'FactoryRuleValidationError' && e.code === 'invalid_factory_rule') {\n    console.error(`Invalid rules config: ${e.message}`); // fix config and reload\n  } else throw e;\n}","preventionTips":["Never use null as an 'empty board' placeholder; always use {}.","Type your config as FactoryRules so TypeScript rejects null at compile time.","Coerce loaded config with ?? {} defaults for each board before validating."],"tags":["validation","type-mismatch","factory-rules","config"],"backgroundTag":"schema-validation-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}