Fixes https://github.com/twentyhq/twenty/issues/20524 ## Problem Adding (or renaming/removing) an option on a `SELECT` / `MULTI_SELECT` field failed for fields whose object + field name combination is long, surfacing to the user only as: > Migration action 'update' for 'fieldMetadata' failed — Migration execution failed. The real underlying Postgres error was: ``` type "_personalInsurancePolicyOrQuote_insuranceCoverageClassification" already exists ALTER TYPE "..."."_personalInsurancePolicyOrQuote_insuranceCoverageClassifications_enum" RENAME TO "..._insuranceCoverageClassifications_enum_old" ``` ## Root cause PostgreSQL truncates identifiers to **63 bytes** (`NAMEDATALEN - 1`). The enum type name `_personalInsurancePolicyOrQuote_insuranceCoverageClassifications_enum` is **69 chars**, so it was already stored truncated to 63 (`..._insuranceCoverageClassification` — the `_enum` suffix chopped off). Multi-select / select option changes go through the rename-and-recreate path in `alterEnumValues`, which renames the enum to `<name>_old`. That candidate is 73 chars → Postgres truncates it back to the **same 63-byte string** as the source → `type "..." already exists`. The failure is deterministic, so every retry on that field failed. The transaction rolls back cleanly, leaving no `_old` artifacts behind. The temporary column name (`<column>_old`) had the same latent bug for very long field names. ## Fix Add `buildTemporaryIdentifier(base, suffix)` to `WorkspaceSchemaEnumManagerService`, which trims the base name so the `_old` suffix survives within 63 bytes and stays distinct from the original. Applied to both the temporary enum name and the temporary column name. The `_old` type/column are transient (dropped within the same transaction), so the trimmed name only needs to fit and not collide — which it now does. ## Test Added `workspace-schema-enum-manager.service.spec.ts` reproducing the exact failing object/field names. Both assertions (target identifier ≤ 63 bytes; truncated source ≠ truncated target) fail on `main` and pass with the fix. ## Recovery No manual cleanup needed for affected workspaces — failed migrations rolled back cleanly. Once deployed, option edits on long-named fields work; the field remained fully usable in the meantime (only option changes were blocked).
The #1 Open-Source CRM
Website ·
Documentation ·
Roadmap ·
Discord ·
Figma
Why Twenty
Twenty gives technical teams the building blocks for a custom CRM that meets complex business needs and quickly adapts as the business evolves. Twenty is the CRM you build, ship, and version like the rest of your stack.
Learn more about why we built Twenty
Installation
Cloud
The fastest way to get started. Sign up at twenty.com and spin up a workspace in under a minute, with no infrastructure to manage and always up to date.
Build an app
Scaffold a new app with the Twenty CLI:
npx create-twenty-app my-app
Define objects, fields, and views as code:
import { defineObject, FieldType } from 'twenty-sdk/define';
export default defineObject({
nameSingular: 'deal',
namePlural: 'deals',
labelSingular: 'Deal',
labelPlural: 'Deals',
fields: [
{ name: 'name', label: 'Name', type: FieldType.TEXT },
{ name: 'amount', label: 'Amount', type: FieldType.CURRENCY },
{ name: 'closeDate', label: 'Close Date', type: FieldType.DATE_TIME },
],
});
Then ship it to your workspace:
npx twenty app:publish --private
See the app development guide for objects, views, agents, and logic functions.
Self-hosting
Run Twenty on your own infrastructure with Docker Compose, or contribute locally via the local setup guide.
Everything you need
Twenty gives you the building blocks of a modern CRM (objects, views, workflows, and agents) and lets you extend them as code. Here's a tour of what's in the box.
Want to go deeper? Read the User Guide for product walkthroughs, or the
Documentation for developer reference.
|
|
|
|
|
|
Stack
TypeScript
Nx
NestJS, with BullMQ,
PostgreSQL,
Redis
React, with Jotai, Linaria and Lingui
Thanks
Thanks to these amazing services that we use and recommend for code review (Greptile), catching bugs (Sentry) and translating (Crowdin).
Join the Community
Star the repo ·
Discord ·
Feature requests ·
Releases ·
X ·
LinkedIn ·
Crowdin ·
Contribute





