actualbudget/actual · error

Only one `up to` allowed per category

Error message

Only one `up to` allowed per category

What it means

A category may have at most one `up to` (limit) clause across its templates. `checkLimit` runs in the CategoryTemplateContext constructor and throws when a second limit directive is found after one was already accepted (`this.limitCheck` is true).

Source

Thrown at packages/loot-core/src/server/budget/category-template-context.ts:588

      t =>
        t.type === 'simple' ||
        t.type === 'periodic' ||
        t.type === 'limit' ||
        t.type === 'remainder',
    )) {
      let limitDef;
      if (template.type === 'limit') {
        limitDef = template;
      } else {
        if (template.limit) {
          limitDef = template.limit;
        } else {
          continue; // may not have a limit defined in the template
        }
      }

      if (this.limitCheck) {
        throw new Error('Only one `up to` allowed per category');
      }

      if (limitDef.period === 'daily') {
        const numDays = monthUtils.differenceInCalendarDays(
          monthUtils.addMonths(this.month, 1),
          this.month,
        );
        this.limitAmount +=
          amountToInteger(limitDef.amount, this.currency.decimalPlaces) *
          numDays;
      } else if (limitDef.period === 'weekly') {
        if (!limitDef.start) {
          throw new Error('Weekly limit requires a start date (YYYY-MM-DD)');
        }
        const nextMonth = monthUtils.nextMonth(this.month);
        let week = limitDef.start;
        const baseLimit = amountToInteger(
          limitDef.amount,

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Remove or comment out one of the `up to` templates so only a single limit remains per category
  2. Combine the intent into one template line with a single `up to` clause

Example fix

// before
#template up to 100
#template 50 up to 200
// after
#template 50 up to 200
Defensive patterns

Strategy: validation

Validate before calling

const upToLines = noteLines.filter(l => /\bup to\b/.test(l));
if (upToLines.length > 1) throw new Error('at most one `up to` clause per category');

Try / catch

try {
  await init();
} catch (e) {
  if (e.message.includes("Only one `up to` allowed")) {
    // remove/merge all but one up-to line in the category note
  } else throw e;
}

Prevention

When it happens

Trigger: Two or more template lines for the same category both define an `up to <amount> ...` limit — e.g. `#template up to 100` plus `#template 50 up to 200` in the same category's note in the same month.

Common situations: Adding a new limit template without removing the old one; merging template lines from two sources; a leftover `up to` from a previous month's note that is still active.

Related errors


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