actualbudget/actual · error
There is already a filter named ${item.name}
Error message
There is already a filter named ${item.name} What it means
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.
Source
Thrown at packages/loot-core/src/server/filters/app.ts:123
if (keys1.length !== keys2.length) {
return false;
}
return keys1.every(key => opt1[key] === opt2[key]);
}
async function createFilter(filter): Promise<TransactionFilterEntity['id']> {
const filterId = uuidv4();
const item = {
id: filterId,
conditions: filter.state.conditions,
conditionsOp: filter.state.conditionsOp,
name: filter.state.name,
};
if (item.name) {
if (await filterNameExists(item.name, item.id, true)) {
throw new Error('There is already a filter named ' + item.name);
}
} else {
throw new Error('Filter name is required');
}
if (item.conditions.length > 0) {
const condExists = conditionExists(item, filter.filters, true);
if (condExists) {
throw new Error(
'Duplicate filter warning: conditions already exist. Filter name: ' +
condExists,
);
}
} else {
throw new Error('Conditions are required');
}
// Create the filter here based on the infoView on GitHub (pinned to d4334cb6e6)
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.
Example fix
// before
await aql.query('filter-create', { state: { name: 'Groceries', conditions, conditionsOp: 'and' } });
// after
const existing = await aql.query('filters'); // or query db directly
if (existing.some(f => f.name === 'Groceries')) {
throw new Error('Please choose a different name');
}
await aql.query('filter-create', { state: { name: 'Groceries', conditions, conditionsOp: 'and' } }); Defensive patterns
Strategy: validation
Validate before calling
const filters = await aql.query('filters');
if (filters.some(f => !f.tombstone && f.name === newName)) {
throw new Error(`Filter name "${newName}" is already in use`);
} Try / catch
try {
await aql.query('filter-create', { state });
} catch (e) {
if (e.message.startsWith('There is already a filter named')) {
// prompt user for a unique name and retry
} else throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Filter name is required
- Conditions are required
- Unknown payee name normalization: ${String(normalization)}
- `date` is required when adding a transaction
- Amount is invalid, must be an integer: ${trans.amount}
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/526edd36b54c7d31.
Report an issue: GitHub.