mastra-ai/mastra · error

Factory work item not found.

Error message

Factory work item not found.

What it means

#requireItem looks up the work item by record.workItemId in storage; if storage.get returns nothing, a plain Error 'Factory work item not found.' is thrown. The decision points at an item id that no longer exists, so dispatch cannot proceed.

Source

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

    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}`);
  }

  async #requireItem(record: FactoryDeferredDecisionRecord) {
    if (!record.workItemId) throw new Error('Factory decision is not linked to a work item.');
    const item = await this.#storage.get({ orgId: record.orgId, id: record.workItemId });
    if (!item) throw new Error('Factory work item not found.');
    return item;
  }

  async #findBinding(
    record: FactoryDeferredDecisionRecord,
    role?: string,
  ): Promise<FactoryRunBindingRecord | undefined> {
    if (!record.workItemId) throw new Error('Factory decision is not linked to a work item.');
    const bindings = await this.#storage.listRunBindings(record.orgId, record.factoryProjectId, record.workItemId);
    return bindings
      .filter(candidate => candidate.status === 'active' && (role === undefined || candidate.role === role))
      .sort((left, right) => {
        if (role === undefined && left.role === 'work' && right.role !== 'work') return -1;
        if (role === undefined && right.role === 'work' && left.role !== 'work') return 1;
        return right.createdAt.getTime() - left.createdAt.getTime() || left.id.localeCompare(right.id);
      })[0];
  }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Confirm the item id and orgId: fetch it directly via storage.get to distinguish deletion from scoping mistakes.
  2. Delete or archive the orphaned decision record so the dispatcher stops retrying it.
  3. Check cleanup/retention jobs for aggressive purging of items referenced by pending decisions.
  4. Re-create the work item (re-materialize from the external source) and re-link the decision.

Example fix

// before: blind retry loop
setInterval(() => dispatchAll(), 60_000);
// after
for (const rec of await listDeferred()) {
  if (!(await storage.get({ orgId: rec.orgId, id: rec.workItemId }))) await storage.deleteDecision(rec.id);
  else await dispatch(rec);
}
Defensive patterns

Strategy: validation

Validate before calling

const item = await storage.get({ orgId: record.orgId, id: record.workItemId });
if (!item) { await purgeDecision(record.id); return; }

Type guard

function itemExists(i: unknown): i is FactoryWorkItem { return typeof (i as any)?.id === 'string'; }

Try / catch

try {
  await dispatcher.dispatch(record);
} catch (e) {
  if (e.message === 'Factory work item not found.') await storage.deleteDecision(record.id);
  else throw e;
}

Prevention

When it happens

Trigger: Dispatching a deferred decision whose workItemId references a deleted work item — e.g. the intake rejection rollback in the same dispatcher deleted the item, external reconciliation removed it, or manual storage cleanup purged it.

Common situations: Cascading deletion (item deleted after a rejected intake), retention/cleanup jobs removing items still referenced by deferred decisions, wrong orgId scoping in manual queries, storage restored from an older backup.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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