SIGN IN SIGN UP

Consolidate the two workspace ORM exception types (#24798)

## What

The follow-up the rename sequence kept deferring: `TwentyORMException`
(v1 era, 51 importers) and `TwentyOrmV2Exception` (28 importers) merge
into a single `TwentyOrmException` in
`twenty-orm/exceptions/twenty-orm.exception.ts`.

- **One code enum**: the union of both, 40 codes. The four overlapping
values (`INVALID_INPUT`, `DUPLICATE_ENTRY_DETECTED`,
`TOO_MANY_RECORDS_TO_UPDATE`, `QUERY_READ_TIMEOUT`) collapse; every code
string value is unchanged, so error extensions on the wire are
identical.
- **One constructor shape**: the options-object form with per-code
user-friendly defaults. The old v2 positional third argument becomes `{
userFriendlyMessage }` at its six call sites.
- **One user-input predicate**: `isTwentyOrmUserInputError` (replacing
`isTwentyOrmV2UserInputError`) unions both sides' user-input codes and
drives the GraphQL handler, the REST handler, and the duplicate-entry
special case (which keeps its conflicting-record extensions).

## Two deliberate harmonizations (the point of consolidating)

- A given code now produces the same user-friendly default no matter
which engine path threw it: v2 throw sites without an explicit message
pick up the established per-code text (for example a bare
`DUPLICATE_ENTRY_DETECTED` now says "A duplicate entry was detected."
instead of the generic fallback).
- REST now returns 400 for every user-input code, including the connect
and RLS codes that GraphQL already treated as user input but REST used
to rethrow as 500.

## Verification

- `tsgo --noEmit` clean, `oxlint --type-aware` and `oxfmt --check src/`
clean
- 171 suites / 1,267 tests pass across twenty-orm, the API handlers and
the exception specs
- Grep gate: `TwentyORMException` and `TwentyOrmV2` no longer appear
anywhere outside translation catalogs
- No committed upgrade command is touched


<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/24798?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
C
Charles Bochet committed
297712a01ae8dc83c8ca98aa5f49a6809b1841a0
Parent: 7253870
Committed by GitHub <noreply@github.com> on 8/25/2026, 5:59:07 PM