diff --git a/packages/twenty-front/src/modules/error-handler/components/AppErrorBoundary.tsx b/packages/twenty-front/src/modules/error-handler/components/AppErrorBoundary.tsx index b6f4a893a8b..d7ef7357272 100644 --- a/packages/twenty-front/src/modules/error-handler/components/AppErrorBoundary.tsx +++ b/packages/twenty-front/src/modules/error-handler/components/AppErrorBoundary.tsx @@ -1,5 +1,6 @@ import { AppErrorBoundaryEffect } from '@/error-handler/components/internal/AppErrorBoundaryEffect'; import { checkIfItsAViteStaleChunkLazyLoadingError } from '@/error-handler/utils/checkIfItsAViteStaleChunkLazyLoadingError'; +import { ObjectMetadataItemNotFoundError } from '@/object-metadata/errors/ObjectMetadataNotFoundError'; import { type ErrorInfo, type ReactNode } from 'react'; import { ErrorBoundary, type FallbackProps } from 'react-error-boundary'; import { type CustomError, isDefined } from 'twenty-shared/utils'; @@ -29,6 +30,13 @@ export const AppErrorBoundary = ({ const fingerprint = hasErrorCode(error) ? error.code : error.message; scope.setFingerprint([fingerprint]); + + if (error instanceof ObjectMetadataItemNotFoundError) { + scope.setLevel('warning'); + scope.setTag('error.category', 'metadata'); + scope.setTag('error.type', 'object-metadata-item-not-found'); + } + error.name = error.message; return scope; }); diff --git a/packages/twenty-front/src/modules/object-metadata/errors/ObjectMetadataNotFoundError.ts b/packages/twenty-front/src/modules/object-metadata/errors/ObjectMetadataNotFoundError.ts index 41a2f2f3cfb..182c3d07641 100644 --- a/packages/twenty-front/src/modules/object-metadata/errors/ObjectMetadataNotFoundError.ts +++ b/packages/twenty-front/src/modules/object-metadata/errors/ObjectMetadataNotFoundError.ts @@ -11,6 +11,7 @@ export class ObjectMetadataItemNotFoundError extends Error { super(message); + this.name = 'ObjectMetadataItemNotFoundError'; Object.setPrototypeOf(this, ObjectMetadataItemNotFoundError.prototype); } } diff --git a/packages/twenty-front/src/modules/settings/data-model/graph-overview/components/SettingsDataModelOverviewEffect.tsx b/packages/twenty-front/src/modules/settings/data-model/graph-overview/components/SettingsDataModelOverviewEffect.tsx index e83f097a397..04b60a3574b 100644 --- a/packages/twenty-front/src/modules/settings/data-model/graph-overview/components/SettingsDataModelOverviewEffect.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/graph-overview/components/SettingsDataModelOverviewEffect.tsx @@ -1,5 +1,5 @@ import { type Edge, type Node } from '@xyflow/react'; -import { useEffect } from 'react'; +import { useEffect, useRef } from 'react'; import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; import { isDefined } from 'twenty-shared/utils'; @@ -17,8 +17,12 @@ export const SettingsDataModelOverviewEffect = ({ }: SettingsDataModelOverviewEffectProps) => { const { activeNonSystemObjectMetadataItems: items } = useFilteredObjectMetadataItems(); + const latestLayoutVersionRef = useRef(0); useEffect(() => { + latestLayoutVersionRef.current += 1; + const currentLayoutVersion = latestLayoutVersionRef.current; + const loadDagreAndLayout = async () => { const dagre = await import('@dagrejs/dagre'); @@ -96,6 +100,10 @@ export const SettingsDataModelOverviewEffect = ({ }; }); + if (currentLayoutVersion !== latestLayoutVersionRef.current) { + return; + } + setNodes(nodes); setEdges(edges); };