twentyhq/twenty · error · Error
Couldn't create step
Error message
Couldn't create step
What it means
Thrown in useCreateStep after createWorkflowVersionStep returns: the stepsDiff contains neither a CREATE entry whose value.id matches the new step id, nor a CHANGE entry containing that id. The backend did not register the new step in the returned diff.
Source
Thrown at packages/twenty-front/src/modules/workflow/workflow-steps/hooks/useCreateStep.ts:85
nextStepId,
position,
parentStepConnectionOptions: connectionOptions,
defaultSettings,
})
)?.data?.createWorkflowVersionStep;
const stepsDiff = workflowVersionStepChanges?.stepsDiff as Difference[];
const addedStepDiff = stepsDiff?.find(
(diff) => diff.type === 'CREATE' && diff.value.id === id,
) as Nullable<DifferenceCreate>;
const createdFirstStepDiff = stepsDiff?.find(
(diff) => diff.type === 'CHANGE' && diff.value?.[0]?.id === id,
) as Nullable<DifferenceChange>;
if (!isDefined(createdFirstStepDiff) && !isDefined(addedStepDiff)) {
throw new Error("Couldn't create step");
}
if (shouldSelectNode) {
setWorkflowSelectedNode(id);
}
setWorkflowLastCreatedStepId(id);
return isDefined(createdFirstStepDiff)
? createdFirstStepDiff.value[0]
: addedStepDiff?.value;
} finally {
setIsLoading(false);
}
};
return {
createStep,
};View on GitHub (pinned to 1f5dd2bbd2)
Solutions
- Inspect the createWorkflowVersionStep GraphQL response (data + errors) in DevTools.
- Confirm newStepType is a valid WorkflowActionType and parentStepId/nextStepId reference existing steps.
- Ensure the workflow version is a DRAFT (getUpdatableWorkflowVersion resolved); if not, a draft creation may have silently failed upstream.
Example fix
// before: if (!isDefined(createdFirstStepDiff) && !isDefined(addedStepDiff)) {
// throw new Error("Couldn't create step");
// }
// after: if (!isDefined(createdFirstStepDiff) && !isDefined(addedStepDiff)) {
// throw new Error(workflowVersionStepChanges?.errors?.[0]?.message ?? "Couldn't create step");
// } Defensive patterns
Strategy: try-catch
Validate before calling
const isValidCreateStepInput = ( stepType: WorkflowActionType, parentStepId: string | undefined, existingStepIds: Set<string>, ): boolean => typeof stepType === 'string' && (parentStepId === undefined || existingStepIds.has(parentStepId));
Type guard
const hasCreateStepDiff = (diff: Difference[] | undefined, id: string): boolean => Array.isArray(diff) && diff.some((d) => d.type === 'CREATE' && (d as any).value?.id === id);
Try / catch
try {
await createStep({ newStepType, parentStepId, nextStepId, ... });
} catch (e) {
showError((e as Error).message); // "Couldn't create step"
} Prevention
- Confirm parentStepId/nextStepId reference current steps at call time.
- Guard against double-submission via the existing isLoading flag.
- Surface backend errors so the generic throw is a last resort.
When it happens
Trigger: Backend rejects the new step (invalid newStepType, parentStepId pointing to a nonexistent step, version in a non-editable state) and returns a 200 with an empty/no-op diff. The returned diff shape differs from expectations. Concurrent edit already removed the parent.
Common situations: Invalid step type. parentStepId/nextStepId stale after another edit. Workflow version locked or already published. Backend bug returning an unchanged diff on success.
Related errors
- No response from server
- Couldn't duplicate step
- Failed to create draft version
- OPERATION_FAILED
- No getAuthTokensFromSSOExchangeToken result
AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12).
Data as JSON: /api/errors/1c4f32d6710f04b3.
Report an issue: GitHub.