mastra-ai/mastra · error · FactoryDispatchError
unsupported_provider_item
unsupported_provider_item
Error message
Factory skill invocation requires one exclusive board stage.
What it means
prepareFactoryRuleBinding maps an external work item to a factory skill invocation, and factoryRuleStage(item.stages) must yield exactly one board stage. When the item has zero or multiple stages (no exclusive stage), the binding cannot be dispatched deterministically, so a FactoryDispatchError with code 'unsupported_provider_item' is thrown.
Source
Thrown at mastracode/factory/src/routes/surface.ts:186
* default model. Exported for tests — this is the autonomous entry point with no
* browser and no interactive user, so nothing else would catch a regression in
* what it forwards.
*/
export async function prepareFactoryRuleBinding(
github: GithubIntegration,
coordinator: Pick<FactoryStartCoordinator, 'prepare'>,
projects: FactoryProjectsStorage,
input: FactoryBindingPreparationInput,
): Promise<void> {
try {
const branch = workItemBranch({
id: input.item.id,
source: workItemBranchSource(input.item.externalSource),
metadata: input.item.metadata,
});
const destinationStage = factoryRuleStage(input.item.stages);
if (!destinationStage) {
throw new FactoryDispatchError(
'unsupported_provider_item',
'Factory skill invocation requires one exclusive board stage.',
);
}
const repositorySlug =
typeof input.item.metadata?.repository === 'string' ? input.item.metadata.repository : undefined;
const preparedSession = await ensureFactorySourceSession({
sourceControl: github.sourceControlStorage,
orgId: input.record.orgId,
factoryProjectId: input.record.factoryProjectId,
repositorySlug,
branch,
// A human-approved proposal has an interactive user: attribute the run to
// the approver, not the repo connector.
attributeToUserId: input.record.approvedBy ?? undefined,
});
await coordinator.prepare({View on GitHub (pinned to 75dd419e61)
Solutions
- Ensure the source work item is assigned to exactly one board stage before the rule triggers.
- Fix provider-side stage configuration so items map to a single column/stage.
- Add a rule filter that skips items without an exclusive stage instead of binding them.
- Inspect item.stages in the payload and normalize it (pick/require one) upstream of prepareFactoryRuleBinding.
Example fix
// before
await prepareFactoryRuleBinding({ item }); // throws when item.stages = []
// after
if (item.stages.length === 1) {
await prepareFactoryRuleBinding({ item });
} else {
logger.warn('Skipping item without exclusive stage', { id: item.id, stages: item.stages });
} Defensive patterns
Strategy: validation
Validate before calling
function hasExclusiveStage(item: { stages: unknown[] }): boolean {
return Array.isArray(item.stages) && item.stages.length === 1;
}
if (!hasExclusiveStage(item)) skipBinding(item); Type guard
function isSingleStageItem(item: { stages: string[] }): item is { stages: [string] } {
return item.stages.length === 1;
} Try / catch
try {
await prepareFactoryRuleBinding(input);
} catch (e) {
if (e instanceof FactoryDispatchError && e.code === 'unsupported_provider_item') {
logger.warn('Work item has no exclusive board stage; skipping', { id: input.item.id, stages: input.item.stages });
return null; // skip instead of failing the whole sync
}
throw e;
} Prevention
- Filter webhook rules to items with exactly one stage/column.
- Normalize multi-stage items upstream (e.g. choose the first stage) before dispatch.
- Alert on provider payloads where stages is empty — usually a board misconfiguration.
When it happens
Trigger: A provider webhook/rule fires for a work item whose stages array is empty or contains more than one stage; syncing items from a board where the card sits in multiple columns or none.
Common situations: Provider boards where items aren't assigned to a column yet (backlog-less items); misconfigured board rules attaching multiple stage labels; provider API changes returning duplicated stage memberships; custom fields mapping several stages onto one item.
Related errors
- ClaudeSDKAgent resumeData must include sessionId or continue
- CursorSDKAgent resumeData must include a message.
- CursorSDKAgent resumeData.agentId must be a string when prov
- CursorSDKAgent does not support structuredOutput because the
- OpenAISDKAgent resumeData must include a message.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/bcf62e8b59d2e858.
Report an issue: GitHub.