{"record":{"id":"4f1786174a8253f8","repo":"mastra-ai/mastra","slug":"factory-rules-github-must-be-an-object","errorCode":null,"errorMessage":"Factory rules.github must be an object.","messagePattern":"Factory rules\\.github must be an object\\.","errorType":"validation","errorClass":"FactoryRuleValidationError","httpStatus":null,"severity":"error","filePath":"mastracode/factory/src/rules/validation.ts","lineNumber":178,"sourceCode":"export function assertFactoryRules(rules: unknown): asserts rules is FactoryRules {\n  if (!isPlainObject(rules)) throw new FactoryRuleValidationError('Factory rules must be an object.');\n  assertExactKeys(rules, ['version', 'work', 'review', 'tools', 'github', 'linear'], 'Factory rules');\n  boundedString(rules.version, 'Factory rule version', MAX_VERSION_LENGTH);\n  validateBoardRules(rules.work, 'Factory rules.work');\n  validateBoardRules(rules.review, 'Factory rules.review');\n\n  if (!isPlainObject(rules.tools)) throw new FactoryRuleValidationError('Factory rules.tools must be an object.');\n  for (const [toolName, leaf] of Object.entries(rules.tools)) {\n    boundedString(toolName, 'Factory tool name', 128, IDENTIFIER_RE);\n    if (!isPlainObject(leaf))\n      throw new FactoryRuleValidationError(`Factory rules.tools.${toolName} must be an object.`);\n    assertExactKeys(leaf, ['onResult'], `Factory rules.tools.${toolName}`);\n    if (leaf.onResult !== undefined && typeof leaf.onResult !== 'function') {\n      throw new FactoryRuleValidationError(`Factory rules.tools.${toolName}.onResult must be a function.`);\n    }\n  }\n\n  if (!isPlainObject(rules.github)) throw new FactoryRuleValidationError('Factory rules.github must be an object.');\n  for (const [event, leaf] of Object.entries(rules.github)) {\n    enumValue(event, FACTORY_GITHUB_EVENTS, 'Factory GitHub event');\n    if (!isPlainObject(leaf)) throw new FactoryRuleValidationError(`Factory rules.github.${event} must be an object.`);\n    assertExactKeys(leaf, ['onEvent'], `Factory rules.github.${event}`);\n    if (leaf.onEvent !== undefined && typeof leaf.onEvent !== 'function') {\n      throw new FactoryRuleValidationError(`Factory rules.github.${event}.onEvent must be a function.`);\n    }\n  }\n\n  if (!isPlainObject(rules.linear)) throw new FactoryRuleValidationError('Factory rules.linear must be an object.');\n  for (const [event, leaf] of Object.entries(rules.linear)) {\n    enumValue(event, FACTORY_LINEAR_EVENTS, 'Factory Linear event');\n    if (!isPlainObject(leaf)) throw new FactoryRuleValidationError(`Factory rules.linear.${event} must be an object.`);\n    assertExactKeys(leaf, ['onEvent'], `Factory rules.linear.${event}`);\n    if (leaf.onEvent !== undefined && typeof leaf.onEvent !== 'function') {\n      throw new FactoryRuleValidationError(`Factory rules.linear.${event}.onEvent must be a function.`);\n    }\n  }","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory/src/rules/validation.ts#L160-L196","documentation":"assertFactoryRules requires rules.github to be a plain object whose keys are valid FACTORY_GITHUB_EVENTS values mapping to { onEvent? } leaves. This error fires when rules.github itself is not a plain object.","triggerScenarios":"rules.github set to null, undefined, an array, a Map, or a primitive while validating the full rules object via prepare or defaultFactoryRules.","commonSituations":"GitHub rules omitted from config and stubbed with null; destructuring/migration code that dropped the github section; an older rules schema where GitHub hooks lived elsewhere and github was never populated.","solutions":["Set rules.github to an object, using {} when no GitHub rules are needed.","Move legacy GitHub hook config into the rules.github shape with valid event keys.","Default on load: rules.github = rules.github ?? {}."],"exampleFix":"// before\n{ version: '1', work: {}, review: {}, tools: {}, github: undefined, linear: {} }\n// after\n{ version: '1', work: {}, review: {}, tools: {}, github: {}, linear: {} }","handlingStrategy":"validation","validationCode":"if (rules.github !== undefined && (rules.github === null || typeof rules.github !== 'object' || Array.isArray(rules.github))) {\n  throw new Error('rules.github must be a plain object (use {} if empty)');\n}","typeGuard":"const isGithubRules = (v: unknown): v is Record<string, { onEvent?: (event: unknown) => unknown }> =>\n  typeof v === 'object' && v !== null && !Array.isArray(v);","tryCatchPattern":"try {\n  assertFactoryRules(rules);\n} catch (e) {\n  if (e.name === 'FactoryRuleValidationError' && /rules\\.github must be an object/.test(e.message)) {\n    rules.github = {}; // default empty GitHub rules and revalidate\n    assertFactoryRules(rules);\n  } else throw e;\n}","preventionTips":["Include github: {} in rules templates even when unused.","Default optional sections with ?? {} at config load time.","Keep a type-annotated FactoryRules object so missing sections are caught before runtime."],"tags":["validation","structure","github","factory-rules"],"backgroundTag":"schema-validation-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}