Sonarly Claude Code 37425f4aae Relation filter key lookup fails when settings.joinColumnName is missing
https://sonarly.com/issue/8007?type=bug

The optimistic cache update for company records crashes because a RELATION filter key (`farmId`) cannot be resolved back to its field metadata — the filter is built using a hardcoded `name + 'Id'` convention, but the reverse lookup relies on `settings.joinColumnName` which may not be populated.

Fix: ## Root Cause Classification: Category A — Logic Error

The naming-convention fallback (`name + 'Id'`) was added for `MORPH_RELATION` fields but was **omitted for regular `RELATION` fields** in two places within `isRecordMatchingFilter.ts`. This is a direct logic omission.

## What was changed

**Fix 1 — Field metadata lookup (lines 200–220)**

Added a 4th fallback in the `objectMetadataField` lookup chain that resolves a filter key like `farmId` back to the `farm` RELATION field using the `name + 'Id'` naming convention:

```typescript file=packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts lines=200-220
const objectMetadataField =
  objectMetadataItem.fields.find((field) => field.name === filterKey) ??
  objectMetadataItem.fields.find(
    (field) =>
      (field.type === FieldMetadataType.RELATION ||
        field.type === FieldMetadataType.MORPH_RELATION) &&
      field.settings?.joinColumnName === filterKey,
  ) ??
  objectMetadataItem.fields.find(
    (field) =>
      field.type === FieldMetadataType.MORPH_RELATION &&
      isMorphRelationJoinColumnKey({ fieldMetadataItem: field, key: filterKey }),
  ) ??
  objectMetadataItem.fields.find(
    (field) =>
      field.type === FieldMetadataType.RELATION &&
      filterKey === `${field.name}Id`,        // NEW: naming-convention fallback
  );
```

**Fix 2 — `isJoinColumn` check in the RELATION switch case (lines 424–432)**

Added the same naming-convention check so that when the resolved field is a `RELATION` type matched via the fallback above, `isJoinColumn` is still `true` and the UUID filter comparison proceeds correctly:

```typescript file=packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts lines=424-432
const isJoinColumn =
  objectMetadataField.settings?.joinColumnName === filterKey ||
  (objectMetadataField.type === FieldMetadataType.RELATION &&
    filterKey === `${objectMetadataField.name}Id`) ||   // NEW: naming-convention fallback
  (objectMetadataField.type === FieldMetadataType.MORPH_RELATION &&
    isMorphRelationJoinColumnKey({
      fieldMetadataItem: objectMetadataField,
      key: filterKey,
    }));
```

## Why this fixes the bug

When a MANY_TO_ONE relation field (e.g., `farm`) has `settings.joinColumnName` not populated (due to the migration gap from the old relation system), the filter key `farmId` produced by `turnRecordFilterIntoGqlOperationFilter` could not be resolved back to any field. The new fallback mirrors exactly what filter construction does — appending `Id` to the field name — so the round-trip always succeeds regardless of whether `settings.joinColumnName` is populated.
2026-03-02 22:25:35 +00:00
2025-08-07 17:02:12 +02:00
2025-07-08 15:13:02 +02:00
2026-02-25 12:26:42 +01:00
2026-02-25 10:35:46 +01:00
2026-03-02 12:06:05 +01:00

Twenty logo

The #1 Open-Source CRM

🌐 Website · 📚 Documentation · Roadmap · Discord · Figma


Cover


Installation

See: 🚀 Self-hosting 🖥️ Local Setup

Why Twenty

We built Twenty for three reasons:

CRMs are too expensive, and users are trapped. Companies use locked-in customer data to hike prices. It shouldn't be that way.

A fresh start is required to build a better experience. We can learn from past mistakes and craft a cohesive experience inspired by new UX patterns from tools like Notion, Airtable or Linear.

We believe in Open-source and community. Hundreds of developers are already building Twenty together. Once we have plugin capabilities, a whole ecosystem will grow around it.


What You Can Do With Twenty

Please feel free to flag any specific needs you have by creating an issue.

Below are a few features we have implemented to date:

Personalize layouts with filters, sort, group by, kanban and table views

Companies Kanban Views

Customize your objects and fields

Setting Custom Objects

Create and manage permissions with custom roles

Permissions

Automate workflow with triggers and actions

Workflows

Emails, calendar events, files, and more

Other Features


Stack

Thanks

Chromatic Greptile Sentry Crowdin E2B

Thanks to these amazing services that we use and recommend for UI testing (Chromatic), code review (Greptile), catching bugs (Sentry) and translating (Crowdin).

Join the Community

Languages
TypeScript 78%
MDX 18.5%
JavaScript 3.1%
Python 0.2%