github →

New request

#20596: v1.20 upgrade flips task/note bodyV2 metadata to TEXT; v2.x silently breaks tasks

We'll provision a sandbox, run an agent against the issue, and open a draft PR. You can pull the branch and iterate from there.

Issue
sonarly:high

Symptom

After upgrading from v1.19.x to v1.20.x, the server starts emitting this on every task/note list or create:

query failed: SELECT "task"."id", ..., "task"."bodyV2" FROM "workspace_xxx"."task" ...
error: column task.bodyV2 does not exist

The UI shows a generic toast. v1.20.x and v1.21.x don't surface it because their TypeORM entity queries the composite columns (bodyV2Blocknote, bodyV2Markdown) directly. From v2.x onwards the entity is built from core."fieldMetadata".type, and if that says TEXT the generated SQL goes after a bodyV2 column that doesn't exist physically.

Evidence

I have three pg_dumpall snapshots, each taken before one step of a v1.19 → v1.20 → v1.21 → v2.0 upgrade sequence. The core."fieldMetadata".type for task.bodyV2/note.bodyV2 in each:

Statetask.bodyV2.type
pre-v1.20 (v1.19.x DB)RICH_TEXT_V2
pre-v1.21 (after v1.19 → v1.20)TEXT
pre-v2.0TEXT
current install (after later upgrades to v2.5.0)TEXT
fresh v2.5.0 install for referenceRICH_TEXT

The physical workspace DDL is bodyV2Blocknote text + bodyV2Markdown text in every snapshot. Only the metadata type is wrong, and it gets wrong specifically during v1.19 → v1.20.

What I think is happening

Three commits land in 11 days on the body-field rename:

46e515436e (PR #18623, 2026-03-13 16:25) introduces packages/twenty-server/src/database/commands/upgrade-version-command/1-20/1-20-migrate-rich-text-to-text.command.ts. The SQL is UPDATE core."fieldMetadata" SET "type" = 'TEXT' WHERE "workspaceId" = $1 AND "type" = 'RICH_TEXT'. The PR deprecates the V1 RICH_TEXT type and converts those rows to TEXT. V2 (RICH_TEXT_V2) is supposed to be left alone.

d9eb317bb5 (PR #18628, 2026-03-13 18:07) renames the enum from RICH_TEXT_V2 = 'RICH_TEXT_V2' to RICH_TEXT = 'RICH_TEXT'. The PR title says "keep DB value", but the diff actually changes the value, not just the key:

-  RICH_TEXT_V2 = 'RICH_TEXT_V2',
+  RICH_TEXT = 'RICH_TEXT',

b709da5825 (2026-03-24) restores it: RICH_TEXT = 'RICH_TEXT_V2'.

So for 11 days the running server's enum says V2 fields have the type 'RICH_TEXT'. Likely cascade: any code path that round-trips a fieldMetadata row through the server (workspace metadata sync, cache rebuild, etc.) writes the row back to the DB using whatever the runtime enum says, so V2 rows get rewritten as 'RICH_TEXT'. Then the 1-20 migration runs, matches them via WHERE type='RICH_TEXT' thinking it's hitting V1 rows, and flips them to 'TEXT'. End result: RICH_TEXT_V2RICH_TEXTTEXT.

I haven't pinpointed the exact code path that does the round-trip. This is the simplest mechanism consistent with the commit timing and the observed end-state. Both #18623 and the later restore are correct in isolation. The bug is that they're separated by 11 days during which V2 rows could get rewritten.

b709da5825 stops new installs from hitting this, but any DB that went through v1.20.x during the window is still in the bad state. No later migration corrects it.

Related: #19207 (closed). Same migration command, opposite end-state — rows stayed at RICH_TEXT_V2 instead of cascading to TEXT. Self-closed by the reporter as a worker-version mismatch.

Reproduction

Reproducing this needs a DB that went through the v1.19 → v1.20 upgrade in the Mar 13 – Mar 24 window with V2 fields present. I have a docker-compose harness that pins TWENTY_TAG and steps through v1.21.0 → v1.22.6 → v2.0.0 → v2.5.0 against a synthetic dump of the bad state. Compose file and synthetic dumps available on request. My original prod dumps can't be shared (GDPR, real customer data).

Workaround

UPDATE core."fieldMetadata" SET type = 'RICH_TEXT' WHERE name = 'bodyV2' AND type = 'TEXT';

Idempotent. Restart the server afterwards so the TypeORM entity rebuilds.


🤖 Drafted and debugged with AI assistance. Even with the help, pinpointing this took a few hours.

Assessmentadvisory
bug●● medium90% confidence

A v1.20 upgrade migration incorrectly rewrites task/note bodyV2 fieldMetadata type from RICH_TEXT_V2 to TEXT, breaking downstream queries.

Likely files
  • packages/twenty-server/src/database/commands/upgrade-version-command/1-20/*
  • packages/twenty-server/src/engine/metadata-modules/field-metadata/*
  • packages/twenty-server/src/engine/workspace-manager/workspace-migration-runner/*
Create the request

This opens a fresh agent run and a draft PR for issue #20596.

Cancel