Compare commits

...
Author SHA1 Message Date
Sonarly Claude Code 0c39034fa7 Nested DragDropContexts cause invariant crash during drag operations
https://sonarly.com/issue/8281?type=bug

The `@hello-pangea/dnd` library throws "Invariant failed" because multiple `DragDropContext` components are nested inside each other, which the library does not support. The outer `PageDragDropProvider` wraps the entire page layout including inner record table/board drag contexts.
2026-03-04 03:57:49 +00:00
Sonarly Claude Code b3b0c27f66 ViewField delete fails: runner loads stale cache after DB cascade deletes viewFields
https://sonarly.com/issue/3344?type=bug

When deactivating a field, the migration runner independently loads flat entity maps from cache to resolve viewField universal identifiers, but a concurrent operation (or the same migration's earlier view delete with DB CASCADE) can remove the viewField from the underlying data between the builder and runner cache reads, causing a lookup failure.

Fix: ## Root Cause

The orchestrator was ordering view-related delete actions with parent `view.delete` **before** child `viewField.delete` (and other child entity deletes). Because `ViewFieldEntity.view` has `onDelete: 'CASCADE'`, when the runner executes `view.delete` it issues a hard `DELETE` against the `view` table; the database CASCADE automatically hard-deletes all child `viewField` rows. However, the runner's optimistic cache update only removes the view from `flatViewMaps` — it does **not** cascade-remove the viewFields from `flatViewFieldMaps`. This leaves a stale/inconsistent optimistic cache.

Then when the runner processes the subsequent `viewField.delete` action, `transpileUniversalDeleteActionToFlatDeleteAction` tries to look up the viewField by its universal identifier in the (now stale) `allFlatEntityMaps`. Since the DB already deleted it via CASCADE, any concurrent operation or cache invalidation that triggers a fresh load will produce a snapshot missing the viewField, causing `findFlatEntityByUniversalIdentifierOrThrow` to throw — wrapped as `WorkspaceMigrationRunnerException` with message `"Migration action 'delete' for 'viewField' failed"`.

## Fix

Reorder the view-related actions in `workspace-migration-build-orchestrator.service.ts` so that all child-entity deletes (`viewFilter`, `viewFilterGroup`, `viewGroup`, `viewFieldGroup`, `viewField`) are executed **before** `view.delete`. This ensures:

1. Child entities are explicitly deleted and removed from the optimistic cache first.
2. When `view.delete` runs and the DB CASCADE fires, there are no remaining child rows in either the DB or the optimistic cache — both are already consistent.
3. The subsequent (now empty) child-delete lists are no-ops, maintaining correctness.

```typescript file=packages/twenty-server/src/engine/workspace-manager/workspace-migration/services/workspace-migration-build-orchestrator.service.ts lines=747-768
// Views
// Child entities must be deleted before parent views to prevent
// DB CASCADE from removing them before the runner's optimistic
// cache processes those delete actions (causing lookup failures).
...aggregatedOrchestratorActionsReport.viewFilter.delete,
...aggregatedOrchestratorActionsReport.viewFilterGroup.delete,
...aggregatedOrchestratorActionsReport.viewGroup.delete,
...aggregatedOrchestratorActionsReport.viewFieldGroup.delete,
...aggregatedOrchestratorActionsReport.viewField.delete,
...aggregatedOrchestratorActionsReport.view.delete,
...aggregatedOrchestratorActionsReport.view.create,
...aggregatedOrchestratorActionsReport.view.update,
...aggregatedOrchestratorActionsReport.viewFieldGroup.create,
...aggregatedOrchestratorActionsReport.viewFieldGroup.update,
...aggregatedOrchestratorActionsReport.viewField.create,
...aggregatedOrchestratorActionsReport.viewField.update,
...aggregatedOrchestratorActionsReport.viewFilterGroup.create,
...aggregatedOrchestratorActionsReport.viewFilterGroup.update,
...aggregatedOrchestratorActionsReport.viewFilter.create,
...aggregatedOrchestratorActionsReport.viewFilter.update,
...aggregatedOrchestratorActionsReport.viewGroup.create,
...aggregatedOrchestratorActionsReport.viewGroup.update,
```

Note: This fix eliminates the intra-migration ordering problem. The separate TOCTOU race between concurrent migrations (independent builder and runner cache reads) remains a narrower architectural gap, but the deterministic failure path described in the Sentry error is resolved by this ordering fix.
2026-03-04 03:52:18 +00:00

Diff Content Not Available