{"record":{"id":"7c4bfe87a067d76d","repo":"mastra-ai/mastra","slug":"factory-rule-decision-type-is-unsupported","errorCode":null,"errorMessage":"Factory rule decision type is unsupported.","messagePattern":"Factory rule decision type is unsupported\\.","errorType":"validation","errorClass":"FactoryRuleValidationError","httpStatus":null,"severity":"error","filePath":"mastracode/factory/src/rules/validation.ts","lineNumber":354,"sourceCode":"      };\n    }\n    case 'notify': {\n      assertExactKeys(value, ['type', 'idempotencyKey', 'title', 'body', 'level'], 'Factory notify decision');\n      const body = optionalBoundedString(value.body, 'Factory notification body', MAX_MESSAGE_LENGTH);\n      const level =\n        value.level === undefined\n          ? undefined\n          : enumValue(value.level, ['info', 'warning', 'error'] as const, 'Factory notification level');\n      return {\n        type,\n        ...commonCommitFields(value),\n        title: boundedString(value.title, 'Factory notification title', MAX_TITLE_LENGTH),\n        ...(body ? { body } : {}),\n        ...(level ? { level } : {}),\n      };\n    }\n    default:\n      throw new FactoryRuleValidationError('Factory rule decision type is unsupported.');\n  }\n}\n\nexport function validateFactoryRuleDecisions(values: readonly unknown[], causalDepth = 0): FactoryCommitDecision[] {\n  if (values.length > MAX_JSON_COLLECTION_SIZE) {\n    throw new FactoryRuleValidationError('Factory rule produced too many decisions.');\n  }\n  const decisions: FactoryCommitDecision[] = [];\n  for (const value of values) {\n    const decision = validateFactoryRuleDecision(value, causalDepth);\n    if (decision.type === 'reject') {\n      throw new FactoryRuleValidationError('A rejection cannot be persisted with commit decisions.');\n    }\n    decisions.push(decision);\n  }\n  const keys = decisions.map(decision => decision.idempotencyKey);\n  if (new Set(keys).size !== keys.length) {\n    throw new FactoryRuleValidationError('Factory decisions require unique idempotency keys.');","sourceCodeStart":336,"sourceCodeEnd":372,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory/src/rules/validation.ts#L336-L372","documentation":"validateFactoryRuleDecision dispatches on the decision's type against the known set of factory commit decision types (message, invoke-skill, link work item, notification, etc.). A decision whose type is not in the switch's known cases falls to the default branch and is rejected, because the dispatcher has no handler for it. This typically means a typo or a decision type from a newer/older schema version.","triggerScenarios":"Emitting a decision with type misspelled (e.g. 'notifcation', 'invokeSkill' vs the exact literal), with wrong casing, or with a type introduced in a different version of the schema than the running factory supports.","commonSituations":"Hand-written rules with a typo in the type literal; rules copied from docs/examples for a different mastracode version; dynamically built type strings (type: `message${suffix}`).","solutions":["Use one of the exact supported decision type literals defined by the FactoryCommitDecision union.","Fix casing/typos — the comparison is exact string equality against the switch cases.","Upgrade or downgrade so the rule's decision types match the factory runtime's schema version.","Check the discriminated-union type errors in your rule's TypeScript build to see the allowed literals."],"exampleFix":"// before\n{ type: 'invokeSkill', skillName: 'deploy' }\n// after\n{ type: 'invoke-skill', skillName: 'deploy' } // exact literal from FactoryCommitDecision union","handlingStrategy":"type-guard","validationCode":"const SUPPORTED_TYPES = new Set(['message', 'invoke-skill', 'link', 'notification', 'reject']); // match library union\nfunction checkType(d) {\n  if (!SUPPORTED_TYPES.has(d.type)) throw new Error(`Unsupported decision type: ${d.type}`);\n}","typeGuard":"type DecisionType = 'message' | 'invoke-skill' | 'link' | 'notification';\nfunction isKnownDecisionType(t: string): t is DecisionType {\n  return ['message', 'invoke-skill', 'link', 'notification'].includes(t);\n}","tryCatchPattern":"try {\n  return validateFactoryRuleDecisions([decision]);\n} catch (e) {\n  if (e instanceof FactoryRuleValidationError && /type is unsupported/.test(e.message)) {\n    throw new Error(`Decision type '${decision.type}' not supported by this factory version; allowed: ${DECISION_TYPES.join(', ')}`);\n  }\n  throw e;\n}","preventionTips":["Type decisions with the library's discriminated union so bad literals fail at compile time.","Never build type strings dynamically with template literals.","Keep rule code on the same schema version as the factory runtime."],"tags":["validation","unsupported-type","factory-rules"],"backgroundTag":"unsupported-discriminant-value","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}