{"record":{"id":"526edd36b54c7d31","repo":"actualbudget/actual","slug":"there-is-already-a-filter-named-item-name","errorCode":null,"errorMessage":"There is already a filter named ${item.name}","messagePattern":"There is already a filter named (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/server/filters/app.ts","lineNumber":123,"sourceCode":"  if (keys1.length !== keys2.length) {\n    return false;\n  }\n\n  return keys1.every(key => opt1[key] === opt2[key]);\n}\n\nasync function createFilter(filter): Promise<TransactionFilterEntity['id']> {\n  const filterId = uuidv4();\n  const item = {\n    id: filterId,\n    conditions: filter.state.conditions,\n    conditionsOp: filter.state.conditionsOp,\n    name: filter.state.name,\n  };\n\n  if (item.name) {\n    if (await filterNameExists(item.name, item.id, true)) {\n      throw new Error('There is already a filter named ' + item.name);\n    }\n  } else {\n    throw new Error('Filter name is required');\n  }\n\n  if (item.conditions.length > 0) {\n    const condExists = conditionExists(item, filter.filters, true);\n    if (condExists) {\n      throw new Error(\n        'Duplicate filter warning: conditions already exist. Filter name: ' +\n          condExists,\n      );\n    }\n  } else {\n    throw new Error('Conditions are required');\n  }\n\n  // Create the filter here based on the info","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/server/filters/app.ts#L105-L141","documentation":"createFilter in packages/loot-core/src/server/filters/app.ts enforces unique names among active (non-tombstoned) transaction filters. Before inserting, it calls filterNameExists(name, id, newItem=true), which returns true if ANY existing filter already uses that name (for new items, even the caller's own id counts). If so, it throws this error to prevent two saved filters sharing a name.","triggerScenarios":"Calling the createFilter mutator (e.g. via filters app/API 'filter-create') with filter.state.name set to a string that already matches the name of any non-deleted row in transaction_filters. Notably, for creation the check is strict: newItem=true means any existing id with that name triggers the error, and tombstoned (deleted) filters are ignored.","commonSituations":"A user (or plugin/script) tries to save a new filter reusing an existing name like 'Groceries big spend'; automated imports or sync re-running createFilter with the same payload; a deleted-but-restored name collision after undo; case is NOT normalized so exact-match duplicates only.","solutions":["Query existing filter names first (SELECT name FROM transaction_filters WHERE tombstone = 0) and pick/require a unique name before calling createFilter.","Catch the error and prompt the user to rename, then retry createFilter with the new name.","If the old filter is no longer wanted, delete it first (tombstone it) so its name is freed, then create.","If updating an existing filter rather than creating, use updateFilter instead, which excludes the filter's own id from the duplicate check."],"exampleFix":"// before\nawait aql.query('filter-create', { state: { name: 'Groceries', conditions, conditionsOp: 'and' } });\n// after\nconst existing = await aql.query('filters'); // or query db directly\nif (existing.some(f => f.name === 'Groceries')) {\n  throw new Error('Please choose a different name');\n}\nawait aql.query('filter-create', { state: { name: 'Groceries', conditions, conditionsOp: 'and' } });","handlingStrategy":"validation","validationCode":"const filters = await aql.query('filters');\nif (filters.some(f => !f.tombstone && f.name === newName)) {\n  throw new Error(`Filter name \"${newName}\" is already in use`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await aql.query('filter-create', { state });\n} catch (e) {\n  if (e.message.startsWith('There is already a filter named')) {\n    // prompt user for a unique name and retry\n  } else throw e;\n}","preventionTips":["Always list existing filters and check the name before creating","Treat filter names as unique keys in any custom UI (enforce in form validation)","For scripts, make filter creation idempotent by searching before inserting"],"tags":["filters","duplicate-name","validation","api"],"backgroundTag":"duplicate-resource-name","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}