Compare commits

...
Author SHA1 Message Date
Sonarly Claude CodeandClaude Opus 4.6 98d3232083 fix: handle stale filter fields in optimistic cache updates
When a saved view filter references a field that no longer exists in the
object metadata (e.g. 'industry' on company), isRecordMatchingFilter
throws an error that crashes the page. This adds try-catch guards around
all isRecordMatchingFilter call sites in Apollo optimistic effect
utilities to gracefully handle stale filters instead of crashing.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-19 10:07:48 +00:00
6 changed files with 76 additions and 41 deletions
@@ -58,11 +58,17 @@ export const processGroupByConnectionWithRecords = ({
let totalCountDelta = 0;
for (const record of records) {
const recordMatchesFilter = isRecordMatchingFilter({
record,
filter: queryFilter ?? {},
objectMetadataItem,
});
let recordMatchesFilter: boolean;
try {
recordMatchesFilter = isRecordMatchingFilter({
record,
filter: queryFilter ?? {},
objectMetadataItem,
});
} catch {
recordMatchesFilter = false;
}
const belongsToGroup = doesRecordBelongToGroup(
record,
@@ -118,11 +118,17 @@ export const triggerUpdateGroupByQueriesOptimisticEffect = ({
> = new Map();
for (const record of records) {
const recordMatchesFilter = isRecordMatchingFilter({
record,
filter: queryFilter ?? {},
objectMetadataItem,
});
let recordMatchesFilter: boolean;
try {
recordMatchesFilter = isRecordMatchingFilter({
record,
filter: queryFilter ?? {},
objectMetadataItem,
});
} catch {
recordMatchesFilter = false;
}
if (
shouldMatchRootQueryFilter &&
@@ -136,14 +136,18 @@ export const triggerCreateRecordsOptimisticEffect = ({
isDefined(rootQueryFilter) &&
shouldMatchRootQueryFilter === true
) {
const recordToCreateMatchesThisRootQueryFilter =
isRecordMatchingFilter({
record: recordToCreate,
filter: rootQueryFilter,
objectMetadataItem,
});
try {
const recordToCreateMatchesThisRootQueryFilter =
isRecordMatchingFilter({
record: recordToCreate,
filter: rootQueryFilter,
objectMetadataItem,
});
if (!recordToCreateMatchesThisRootQueryFilter) {
if (!recordToCreateMatchesThisRootQueryFilter) {
return false;
}
} catch {
return false;
}
}
@@ -57,14 +57,20 @@ export const triggerDestroyRecordsOptimisticEffect = ({
rootQueryCachedResponse,
);
const recordsMatchingRootQueryFilter = recordsToDestroy.filter(
(record) =>
isRecordMatchingFilter({
record,
filter: rootQueryVariables?.filter ?? {},
objectMetadataItem,
}),
);
let recordsMatchingRootQueryFilter: RecordGqlNode[];
try {
recordsMatchingRootQueryFilter = recordsToDestroy.filter(
(record) =>
isRecordMatchingFilter({
record,
filter: rootQueryVariables?.filter ?? {},
objectMetadataItem,
}),
);
} catch {
recordsMatchingRootQueryFilter = [];
}
const newTotalCount = isDefined(totalCount)
? Math.max(totalCount - recordsMatchingRootQueryFilter.length, 0)
@@ -76,17 +76,24 @@ export const triggerUpdateRecordOptimisticEffect = ({
const rootQueryFilter = rootQueryVariables?.filter;
const rootQueryOrderBy = rootQueryVariables?.orderBy;
const updatedRecordMatchesThisRootQueryFilter = isRecordMatchingFilter({
record: updatedRecord,
filter: rootQueryFilter ?? {},
objectMetadataItem,
});
let updatedRecordMatchesThisRootQueryFilter: boolean;
let currentRecordIndexInRootQueryEdges: boolean;
const currentRecordIndexInRootQueryEdges = isRecordMatchingFilter({
record: currentRecord,
filter: rootQueryFilter ?? {},
objectMetadataItem,
});
try {
updatedRecordMatchesThisRootQueryFilter = isRecordMatchingFilter({
record: updatedRecord,
filter: rootQueryFilter ?? {},
objectMetadataItem,
});
currentRecordIndexInRootQueryEdges = isRecordMatchingFilter({
record: currentRecord,
filter: rootQueryFilter ?? {},
objectMetadataItem,
});
} catch {
return rootQueryCachedResponse;
}
const totalCount = readField<number | undefined>(
'totalCount',
@@ -80,12 +80,18 @@ export const triggerUpdateRecordOptimisticEffectByBatch = ({
const rootQueryOrderBy = rootQueryVariables?.orderBy;
for (const updatedRecord of updatedRecords) {
const updatedRecordMatchesThisRootQueryFilter =
isRecordMatchingFilter({
record: updatedRecord,
filter: rootQueryFilter ?? {},
objectMetadataItem,
});
let updatedRecordMatchesThisRootQueryFilter: boolean;
try {
updatedRecordMatchesThisRootQueryFilter =
isRecordMatchingFilter({
record: updatedRecord,
filter: rootQueryFilter ?? {},
objectMetadataItem,
});
} catch {
continue;
}
const updatedRecordFoundInRootQueryEdges = isDefined(
rootQueryCurrentEdges.find(