mastra-ai/mastra · error
Factory decision is not linked to a work item.
Error message
Factory decision is not linked to a work item.
What it means
#requireItem enforces that a deferred decision record carries a workItemId before doing anything item-related. If record.workItemId is falsy, a plain Error 'Factory decision is not linked to a work item.' is thrown. It indicates a data-integrity problem: a decision was deferred/persisted without ever being linked to a created work item.
Source
Thrown at mastracode/factory/src/rules/dispatcher.ts:808
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}`);
}
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
- Query storage for decisions with null workItemId and delete or re-enqueue them after re-materializing the item.
- Fix the upstream step that should create the work item and set workItemId before deferral completes.
- If constructing records manually (tests), always set workItemId to a valid stored item id.
Example fix
// before dispatch(record); // record.workItemId missing // after if (!record.workItemId) record = await reMaterializeAndLink(record); await dispatcher.dispatch(record);
Defensive patterns
Strategy: validation
Validate before calling
function canDispatch(record: FactoryDeferredDecisionRecord): boolean {
return typeof record.workItemId === 'string' && record.workItemId.length > 0;
} Type guard
function isLinkedDecision(r: FactoryDeferredDecisionRecord): r is FactoryDeferredDecisionRecord & { workItemId: string } {
return typeof r.workItemId === 'string' && r.workItemId.length > 0;
} Try / catch
try {
await dispatcher.dispatch(record);
} catch (e) {
if (e.message === 'Factory decision is not linked to a work item.') await reMaterializeAndLink(record);
else throw e;
} Prevention
- Never persist deferred decisions without a workItemId.
- Add a startup sweeper for orphan decisions lacking a work item link.
- Validate records at storage write time with a schema.
When it happens
Trigger: Calling dispatcher paths that resolve the work item (#requireItem via binding/session preparation) with a FactoryDeferredDecisionRecord whose workItemId is null/undefined — e.g. a record saved before item creation failed, or a manually constructed record.
Common situations: A previous dispatch crashed between deferral and item creation, leaving an orphan decision record; importing/restoring storage data that lost the link; tests constructing partial records.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- ${initial.code}: ${initial.reason}
- ${moved.code}: ${moved.reason}
- Factory work item not found.
- session_unavailable
- Factory binding ${binding.id} has no authenticated session o
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/13bfeff9c465142c.
Report an issue: GitHub.