{"record":{"id":"09e7fd189c80a2de","repo":"refinedev/refine","slug":"max-deep-reached","errorCode":null,"errorMessage":"Max deep reached","messagePattern":"Max deep reached","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/appwrite/src/utils/generateFilter.ts","lineNumber":15,"sourceCode":"import type { CrudFilter } from \"@refinedev/core\";\nimport { Query } from \"appwrite\";\nimport { replaceIdWithAppwriteId } from \"./replaceIdWithAppwriteId\";\n\n/**\n * Generate a filter string for Appwrite from Refine's filter\n * @param filter Refine's filter\n * @param deep Max deep of the filter\n * @returns Appwrite's filter string\n */\nexport const generateFilter = (filter: CrudFilter, deep = 10): string => {\n  const nextDeep = deep - 1;\n\n  if (nextDeep < 0) {\n    throw new Error(\"Max deep reached\");\n  }\n\n  filter = replaceIdWithAppwriteId(filter);\n\n  switch (filter.operator) {\n    // Logical operators\n    case \"eq\":\n      return Query.equal(filter.field, filter.value);\n    case \"ne\":\n      return Query.notEqual(filter.field, filter.value);\n    case \"gt\":\n      return Query.greaterThan(filter.field, filter.value);\n    case \"gte\":\n      return Query.greaterThanEqual(filter.field, filter.value);\n    case \"lt\":\n      return Query.lessThan(filter.field, filter.value);\n    case \"lte\":\n      return Query.lessThanEqual(filter.field, filter.value);","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/refinedev/refine/blob/779d52a20e29b0307ac0df04d135beba434370dc/packages/appwrite/src/utils/generateFilter.ts#L1-L33","documentation":"Thrown by refine's Appwrite data provider when a CrudFilter logical operator chain (and/or/nested) exceeds the maximum recursion depth of 10 in generateFilter. It prevents infinite or pathological recursion while translating refine filters into Appwrite Query strings.","triggerScenarios":"Passing a filter with more than 10 levels of nested logical operators (and/or) to the Appwrite data provider's getList, e.g. filter: { operator: 'or', value: [{ operator: 'or', value: [...10+ levels deep...] }] }.","commonSituations":"Programmatically generated filters (e.g. from a filter builder UI or a loop) that nest logical groups more than 10 levels; converting deeply nested filters from another data provider to Appwrite.","solutions":["Flatten the filter tree so logical nesting stays under 10 levels (e.g. merge nested 'or' branches into one level)","If filters are machine-generated, cap or simplify the generated structure before passing it to the data provider","As a last resort, fork/patch generateFilter to raise the deep limit"],"exampleFix":"// before\nconst f = { operator: 'or', value: [{ operator: 'or', value: [{ operator: 'or', value: [/* ...deep... */] }] }] };\ndataProvider.getList({ resource: 'posts', filters: [f] });\n// after\nconst f = { operator: 'or', value: [cond1, cond2, cond3] }; // flattened, depth < 10\ndataProvider.getList({ resource: 'posts', filters: [f] });","handlingStrategy":"validation","validationCode":"const filterDepth = (f) => f.operator === 'and' || f.operator === 'or' ? 1 + Math.max(0, ...f.value.map(filterDepth)) : 0;\nif (filterDepth(filter) >= 10) throw new Error('Filter too deep — flatten before sending');\nawait dataProvider.getList({ resource: 'posts', filters: [filter] });","typeGuard":"const isLogical = (f) => f.operator === 'and' || f.operator === 'or';","tryCatchPattern":"try { await dataProvider.getList({ resource, filters }); } catch (e) { if (e.message === 'Max deep reached') { /* flatten filters and retry */ } else throw e; }","preventionTips":["Flatten and/or chains when building filters programmatically","Cap nesting depth in your own filter-builder UI"],"tags":["appwrite","filter","recursion","data-provider"],"backgroundTag":"filter-depth-limit-exceeded","analyzedSha":"779d52a20e29b0307ac0df04d135beba434370dc","analyzedAt":"2026-08-27T11:15:25.854Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}