mastra-ai/mastra · error · FactoryRuleValidationError

Factory rule decision type is unsupported.

Error message

Factory rule decision type is unsupported.

What it means

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.

Source

Thrown at mastracode/factory/src/rules/validation.ts:354

      };
    }
    case 'notify': {
      assertExactKeys(value, ['type', 'idempotencyKey', 'title', 'body', 'level'], 'Factory notify decision');
      const body = optionalBoundedString(value.body, 'Factory notification body', MAX_MESSAGE_LENGTH);
      const level =
        value.level === undefined
          ? undefined
          : enumValue(value.level, ['info', 'warning', 'error'] as const, 'Factory notification level');
      return {
        type,
        ...commonCommitFields(value),
        title: boundedString(value.title, 'Factory notification title', MAX_TITLE_LENGTH),
        ...(body ? { body } : {}),
        ...(level ? { level } : {}),
      };
    }
    default:
      throw new FactoryRuleValidationError('Factory rule decision type is unsupported.');
  }
}

export function validateFactoryRuleDecisions(values: readonly unknown[], causalDepth = 0): FactoryCommitDecision[] {
  if (values.length > MAX_JSON_COLLECTION_SIZE) {
    throw new FactoryRuleValidationError('Factory rule produced too many decisions.');
  }
  const decisions: FactoryCommitDecision[] = [];
  for (const value of values) {
    const decision = validateFactoryRuleDecision(value, causalDepth);
    if (decision.type === 'reject') {
      throw new FactoryRuleValidationError('A rejection cannot be persisted with commit decisions.');
    }
    decisions.push(decision);
  }
  const keys = decisions.map(decision => decision.idempotencyKey);
  if (new Set(keys).size !== keys.length) {
    throw new FactoryRuleValidationError('Factory decisions require unique idempotency keys.');

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Use one of the exact supported decision type literals defined by the FactoryCommitDecision union.
  2. Fix casing/typos — the comparison is exact string equality against the switch cases.
  3. Upgrade or downgrade so the rule's decision types match the factory runtime's schema version.
  4. Check the discriminated-union type errors in your rule's TypeScript build to see the allowed literals.

Example fix

// before
{ type: 'invokeSkill', skillName: 'deploy' }
// after
{ type: 'invoke-skill', skillName: 'deploy' } // exact literal from FactoryCommitDecision union
Defensive patterns

Strategy: type-guard

Validate before calling

const SUPPORTED_TYPES = new Set(['message', 'invoke-skill', 'link', 'notification', 'reject']); // match library union
function checkType(d) {
  if (!SUPPORTED_TYPES.has(d.type)) throw new Error(`Unsupported decision type: ${d.type}`);
}

Type guard

type DecisionType = 'message' | 'invoke-skill' | 'link' | 'notification';
function isKnownDecisionType(t: string): t is DecisionType {
  return ['message', 'invoke-skill', 'link', 'notification'].includes(t);
}

Try / catch

try {
  return validateFactoryRuleDecisions([decision]);
} catch (e) {
  if (e instanceof FactoryRuleValidationError && /type is unsupported/.test(e.message)) {
    throw new Error(`Decision type '${decision.type}' not supported by this factory version; allowed: ${DECISION_TYPES.join(', ')}`);
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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}`).

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/7c4bfe87a067d76d. Report an issue: GitHub.