Compare commits

...
Author SHA1 Message Date
Sonarly Claude Code 8d5104eb18 Debounced workflow step update throws during auth token renewal window
https://sonarly.com/issue/5150?type=bug

The debounced `updateAction` callback in the workflow code editor fires while workflow data is temporarily `undefined` due to an in-progress authentication token renewal, causing `getUpdatableWorkflowVersion()` to throw an unrecoverable error.

Fix: The fix adds a `!isDefined(workflow)` guard to the `updateAction` debounced callback in `WorkflowEditActionCode.tsx`, mirroring the existing guard already present in `handleCodeChange`.

During auth token renewal, all active Apollo queries are invalidated and must be re-fetched. This leaves `workflow` temporarily `undefined`. The debounced `updateAction` (500ms delay) can fire within this window, calling `actionOptions.onActionUpdate` → `updateStep` → `getUpdatableWorkflowVersion()`, which throws when `workflow` is `undefined`.

The fix is a one-line change — adding `|| !isDefined(workflow)` to the existing `readonly` check:

```typescript file=packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionCode.tsx lines=255-267
const updateAction = useDebouncedCallback(
    (actionUpdate: Partial<WorkflowCodeAction>) => {
      if (actionOptions.readonly === true || !isDefined(workflow)) {  // ← added guard
        return;
      }

      actionOptions.onActionUpdate({
        ...action,
        ...actionUpdate,
      });
    },
    500,
  );
```

This is consistent with the sibling `handleCodeChange` function (line 270) which already has the same `!isDefined(workflow)` guard. The edit in progress at the time of the debounce fire will be silently dropped (not persisted), which is the same behaviour as `handleCodeChange` — the user may need to re-type their last keystroke after the token renewal completes, but no unrecoverable error is thrown.
2026-03-04 10:30:15 +00:00
@@ -254,7 +254,7 @@ export const WorkflowEditActionCode = ({
const updateAction = useDebouncedCallback(
(actionUpdate: Partial<WorkflowCodeAction>) => {
if (actionOptions.readonly === true) {
if (actionOptions.readonly === true || !isDefined(workflow)) {
return;
}