mastra-ai/mastra · error
${result.reason}
Error message
${result.reason} What it means
In useBoardComposer.submit, a manual creation flow first transitions the item on the work board via transition.mutateAsync; if the transition result status is 'rejected', the server-provided reason string is thrown verbatim as an Error. The message content is therefore whatever the board-transition service rejected with.
Source
Thrown at mastracode/factory-ui/src/ui/domains/factory/hooks/useBoardComposer.ts:47
/**
* Submits are re-entrant: a rejected transition keeps the composer open, so a
* retry must update the card it already created instead of filing a duplicate.
*/
const submit = async (forStage: BoardStageId, title: string) => {
const pendingItem = pendingItemRef.current?.stage === forStage ? pendingItemRef.current : undefined;
let item: WorkItem;
if (pendingItem === undefined) {
item = await create.mutateAsync({ source: 'manual', sourceKey: null, title, stages: ['intake'] });
pendingItemRef.current = { stage: forStage, title, item };
} else if (pendingItem.title !== title) {
item = await update.mutateAsync({ id: pendingItem.item.id, patch: { title } });
pendingItemRef.current = { stage: forStage, title, item };
} else {
item = pendingItem.item;
}
if (forStage !== 'intake') {
const result = await transition.mutateAsync({ item, board: 'work', stage: forStage, cause: 'manual_creation' });
if (result.status === 'rejected') throw new Error(result.reason);
}
pendingItemRef.current = undefined;
};
return {
stage,
open: setStage,
close: (closing: BoardStageId) => {
if (pendingItemRef.current?.stage === closing) pendingItemRef.current = undefined;
closedStageRef.current = closing;
setStage(current => (current === closing ? undefined : current));
},
registerTrigger: (forStage: BoardStageId) => (element: HTMLButtonElement | null) => {
if (element) triggerRefs.current.set(forStage, element);
else triggerRefs.current.delete(forStage);
},
submit,
};View on GitHub (pinned to 75dd419e61)
Solutions
- Read the thrown message — it is the server's rejection reason — and address that specific rule/permission issue.
- Refresh the board/item state before retrying (the local item may be stale).
- Verify the target stage is valid for the item type and the user has transition permission.
- Prevent concurrent edits (single-tab workflows or optimistic-locking on the server).
Example fix
// before
if (result.status === 'rejected') throw new Error(result.reason);
// after
if (result.status === 'rejected') {
await queryClient.invalidateQueries(['board', 'work']);
throw new Error(result.reason);
} Defensive patterns
Strategy: try-catch
Type guard
type TransitionResult = { status: 'ok' } | { status: 'rejected'; reason: string };
function isRejected(r: TransitionResult): r is { status: 'rejected'; reason: string } {
return r.status === 'rejected';
} Try / catch
try {
await submit({ forStage, title, item });
} catch (e) {
showToast(e instanceof Error ? e.message : 'Board transition rejected');
await queryClient.invalidateQueries({ queryKey: ['board'] }); // resync stale state
} Prevention
- Refresh board state before retrying after a rejection.
- Check permissions and stage rules for the item type before submit.
- Avoid concurrent edits of the same item across tabs.
When it happens
Trigger: Submitting a composer item for a non-intake stage while the server rejects the board transition (invalid stage for the item, item locked/already moved, permission denied, or conflicting concurrent transition) — result.status === 'rejected' with a reason.
Common situations: Two tabs moving the same card concurrently; target stage not allowed by board rules for that item type; user lacks write permission on the board; stale item state after another actor changed it.
Related errors
- Agent "${agentId}" is already connected to Slack. Disconnect
- Agent "${agentId}" is already connected to Telegram. Disconn
- No Telegram installation found for agent "${agentId}"
- Session settings are unavailable
- Failed to load models (${res.status})
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/aa05f6fa719ec6d8.
Report an issue: GitHub.