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.
The #1 Open-Source CRM
🌐 Website · 📚 Documentation · Roadmap ·
Discord ·
Figma
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
- Customize your objects and fields
- Create and manage permissions with custom roles
- Automate workflow with triggers and actions
- Emails, calendar events, files, and more
Personalize layouts with filters, sort, group by, kanban and table views
Customize your objects and fields
Create and manage permissions with custom roles
Automate workflow with triggers and actions
Emails, calendar events, files, and more
Stack
- TypeScript
- Nx
- NestJS, with BullMQ, PostgreSQL, Redis
- React, with Jotai, Emotion and Lingui
Thanks
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
- Star the repo
- Subscribe to releases (watch -> custom -> releases)
- Follow us on Twitter or LinkedIn
- Join our Discord
- Improve translations on Crowdin
- Contributions are, of course, most welcome!




