mastra-ai/mastra · error

${initial.code}: ${initial.reason}

Error message

${initial.code}: ${initial.reason}

What it means

During deferred-decision dispatch, the dispatcher first materializes the linked item ('intake' stage). If that initial transition comes back with status 'rejected', it rolls back the just-created work item and throws a plain Error formatted as '<code>: <reason>'. This prevents the decision from proceeding when the rule engine explicitly rejects the initial stage.

Source

Thrown at mastracode/factory/src/rules/dispatcher.ts:786

    const board = decision.board;
    let expectedRevision = result.item.revision;
    if (materializedByDecision) {
      const initial = await this.#transitionService.transition({
        orgId: record.orgId,
        factoryProjectId: record.factoryProjectId,
        workItemId: result.item.id,
        board,
        stage: 'intake',
        expectedRevision,
        actor: deferredActor(record),
        ingress: { type: 'rule', identity: `decision:${record.idempotencyKey}:${result.item.id}:initial-entry` },
        cause: 'linked_item_materialized',
        causalChain,
        initialEntry: true,
      });
      if (initial.status === 'rejected') {
        if (result.created) await this.#storage.delete({ orgId: record.orgId, id: result.item.id });
        throw new Error(`${initial.code}: ${initial.reason}`);
      }
      expectedRevision = initial.revision;
    }
    if (decision.stage === 'intake') return;

    const moved = await this.#transitionService.transition({
      orgId: record.orgId,
      factoryProjectId: record.factoryProjectId,
      workItemId: result.item.id,
      board,
      stage: decision.stage,
      expectedRevision,
      actor: { type: 'system', id: 'factory-rule-dispatcher' },
      ingress: { type: 'rule', identity: `decision:${record.idempotencyKey}:${result.item.id}:destination` },
      cause: materializedByDecision ? 'linked_item_materialized' : 'linked_item_reconciled',
      causalChain,
    });
    if (moved.status === 'rejected') throw new Error(`${moved.code}: ${moved.reason}`);

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Parse the thrown message's leading code to identify which rejection reason the rules produced.
  2. Inspect the rule definitions for the factory project and confirm one should match this decision.
  3. Verify the rule version pinned on the factory matches the rules you intend to evaluate.
  4. Re-run the decision after correcting rules/binding; note the created work item was deleted so no cleanup is needed.

Example fix

// before: swallow the failure
catch (e) { /* ignore */ }
// after
try { await dispatcher.dispatch(record); }
catch (e) {
  const [code, ...reason] = e.message.split(': ');
  console.warn(`decision rejected: ${code} — ${reason.join(': ')}`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

const decision = await evaluateRulesFor(record);
if (decision.status === 'rejected') skipDispatch(record, decision.reason);

Type guard

function isRejectionError(e: unknown): e is Error & { code: string; reason: string } {
  return e instanceof Error && /^[a-z_]+: .+/.test(e.message);
}

Try / catch

try {
  await dispatcher.dispatch(record);
} catch (e) {
  const m = /^[^:]+: (.+)$/.exec(e.message);
  if (m) log(`initial intake rejected: ${m[1]}`);
  else throw e;
}

Prevention

When it happens

Trigger: Processing a deferred factory decision whose initial intake transition is rejected by the rule evaluation — e.g. no rule matched, a guard/condition failed, or the rule outcome evaluated to rejected for the linked item.

Common situations: A rule version bump changed matching semantics so previously-accepted items are now rejected; a missing rule binding for the project; malformed decision payload that fails rule conditions.

Related errors


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