actualbudget/actual · error

Conditions are required

Error message

Conditions are required

What it means

createFilter requires at least one condition. If filter.state.conditions is an empty array (length 0), the else branch throws 'Conditions are required'. A saved filter with no conditions would match nothing and is considered invalid.

Source

Thrown at packages/loot-core/src/server/filters/app.ts:138

  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 info
  await db.insertWithSchema('transaction_filters', filterModel.fromJS(item));

  return filterId;
}

async function updateFilter(filter) {
  const item = {
    id: filter.state.id,
    conditions: filter.state.conditions,
    conditionsOp: filter.state.conditionsOp,
    name: filter.state.name,
  };
  if (item.name) {
    if (await filterNameExists(item.name, item.id, false)) {
      throw new Error('There is already a filter named ' + item.name);

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Ensure state.conditions contains at least one condition object ({field, op, value, options}) before calling createFilter.
  2. Validate conditions.length > 0 client-side and disable save until a condition is added.
  3. Catch the error and surface 'add a condition' guidance to the user.

Example fix

// before
await aql.query('filter-create', { state: { name: 'My filter', conditions: [], conditionsOp: 'and' } });
// after
const conditions = [{ field: 'amount', op: 'gt', value: 100, options: [] }];
if (conditions.length === 0) throw new Error('Add at least one condition');
await aql.query('filter-create', { state: { name: 'My filter', conditions, conditionsOp: 'and' } });
Defensive patterns

Strategy: validation

Validate before calling

if (!Array.isArray(state.conditions) || state.conditions.length === 0) {
  throw new Error('At least one condition is required');
}

Type guard

function hasConditions(state: { conditions?: unknown[] }): state is { conditions: [unknown, ...unknown[]] } {
  return Array.isArray(state.conditions) && state.conditions.length > 0;
}

Try / catch

try {
  await aql.query('filter-create', { state });
} catch (e) {
  if (e.message === 'Conditions are required') {
    // guide the user to add a condition
  } else throw e;
}

Prevention

When it happens

Trigger: Calling filter-create with state.conditions = []; a UI allowing the save button while the condition builder is empty; a script constructing a filter payload with an unpopulated conditions array.

Common situations: Custom frontends on the Actual API that don't enforce at least one rule row; bulk-import tooling writing filters with placeholder empty conditions; race where conditions are cleared before submit.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29). Data as JSON: /api/errors/670d4a9c2d6707d3. Report an issue: GitHub.