{"record":{"id":"bd1e99102bbc1f8a","repo":"mem0ai/mem0","slug":"oracle-filter-groups-must-be-non-empty-objects","errorCode":null,"errorMessage":"Oracle filter groups must be non-empty objects","messagePattern":"Oracle filter groups must be non-empty objects","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mem0-ts/src/oss/src/vector_stores/oracledb.ts","lineNumber":253,"sourceCode":"      passings.push(passing);\n    }\n  }\n\n  const clauses = [...additionalClauses];\n  if (predicates.length > 0) {\n    clauses.unshift(jsonExists(path, predicates.join(\" && \"), passings));\n  }\n\n  return clauses.length === 1 ? clauses[0] : `(${clauses.join(\" AND \")})`;\n}\n\nexport function buildFilterGroup(\n  filters: Record<string, any>,\n  binds: Record<string, any>,\n): string {\n  const entries = Object.entries(filters ?? {});\n  if (entries.length === 0) {\n    throw new Error(\"Oracle filter groups must be non-empty objects\");\n  }\n\n  const clauses: string[] = [];\n  for (const [key, value] of entries) {\n    const logicalOperator = LOGICAL_OPERATORS[key];\n    if (logicalOperator) {\n      if (!Array.isArray(value) || value.length === 0) {\n        throw new Error(\n          `Logical filter operator '${key}' requires a non-empty array`,\n        );\n      }\n      const nested = value.map((condition) =>\n        buildFilterGroup(condition, binds),\n      );\n      if (logicalOperator === \"not\") {\n        clauses.push(`NOT (${nested.join(\" OR \")})`);\n      } else {\n        clauses.push(","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/oss/src/vector_stores/oracledb.ts#L235-L271","documentation":"buildFilterGroup requires a non-empty filter object so it can emit at least one SQL clause; Object.entries(filters ?? {}) returning zero entries means there is nothing to translate. Note that undefined/null filters never reach here (buildWhereClause short-circuits them) — only an explicitly empty object {} or an empty nested group triggers it.","triggerScenarios":"search('q', { filters: {} }); or a nested group like { $and: [{}] } where an inner condition object is empty; also { $or: [] } style inputs filtered down to an empty object by upstream code.","commonSituations":"Dynamically composing filters where every optional key was omitted, leaving {}; spreading optional params into a base object that stays empty; forwarding a client's {} query parameter verbatim.","solutions":["Pass undefined (or omit the filters key) instead of an empty object when no filtering is needed.","In filter-composition helpers, return undefined when the resulting object has no keys.","Validate and drop empty nested groups: { $and: parts.filter(p => Object.keys(p).length > 0) }.","Add an application-level check before search(): if (!Object.keys(filters).length) filters = undefined."],"exampleFix":"// before\nawait memory.search('q', { filters: {} });\n\n// after\nconst filters = Object.keys(built).length ? built : undefined;\nawait memory.search('q', { filters });","handlingStrategy":"validation","validationCode":"function dropEmptyGroups(filters: any): any {\n  if (Array.isArray(filters)) {\n    const nested = filters.map(dropEmptyGroups).filter((f) => f !== undefined);\n    return nested; // caller decides whether the array is still non-empty\n  }\n  if (!filters || typeof filters !== 'object') return filters;\n  const out: Record<string, any> = {};\n  for (const [k, v] of Object.entries(filters)) {\n    if (v && typeof v === 'object' && !Array.isArray(v) && Object.keys(v).length === 0) continue;\n    out[k] = dropEmptyGroups(v);\n  }\n  return Object.keys(out).length ? out : undefined;\n}","typeGuard":"const isNonEmptyFilterObject = (v: unknown): v is Record<string, unknown> =>\n  !!v && typeof v === 'object' && !Array.isArray(v) && Object.keys(v).length > 0;","tryCatchPattern":null,"preventionTips":["Pass undefined instead of {} when no filters apply.","Compose filters with helpers that return undefined for empty results.","Strip empty nested groups before search()."],"tags":["oracle","filters","validation","empty-object"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}