actualbudget/actual · error

Only one spend template is allowed per category

Error message

Only one spend template is allowed per category

What it means

Only one `spend` template may exist per category per month. `checkSpend`, invoked from the CategoryTemplateContext constructor, counts templates of type 'spend' for the category and throws if more than one is present, since multiple spend goals would be ambiguous.

Source

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

      if (this.fromLastMonth >= this.limitAmount) {
        this.limitMet = true;
        if (this.limitHold) {
          this.limitExcess = 0;
          this.toBudgetAmount = 0;
          this.fullAmount = 0;
        } else {
          this.limitExcess = this.fromLastMonth - this.limitAmount;
          this.toBudgetAmount = -this.limitExcess;
          this.fullAmount = -this.limitExcess;
        }
      }
    }
  }

  private checkSpend() {
    const st = this.templates.filter(t => t.type === 'spend');
    if (st.length > 1) {
      throw new Error('Only one spend template is allowed per category');
    }
  }

  private checkGoal() {
    if (this.goals.length > 1) {
      throw new Error(`Only one #goal is allowed per category`);
    }
  }

  private removeFraction(amount: number): number {
    return amountToInteger(
      Math.round(integerToAmount(amount, this.currency.decimalPlaces)),
      this.currency.decimalPlaces,
    );
  }

  //-----------------------------------------------------------------------------
  //  Processor Functions

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Delete one of the spend template lines so only a single spend goal remains for that category
  2. Merge the two goals into one spend template with a single target amount and date

Example fix

// before
#template spend 200
#template spend 300
// after
#template spend 300
Defensive patterns

Strategy: validation

Validate before calling

const spendLines = noteLines.filter(l => /#template\s+spend/.test(l));
if (spendLines.length > 1) throw new Error('only one spend template per category');

Try / catch

try {
  await init();
} catch (e) {
  if (e.message === 'Only one spend template is allowed per category') {
    // delete or merge one of the spend lines in the category note
  } else throw e;
}

Prevention

When it happens

Trigger: A category's templates for the month contain two or more `#template spend ...` (or `template up to spend` variants) lines, e.g. `#template spend 200` and `#template spend from 2024-01-01` both active in the same category.

Common situations: Adding a new spend goal without deleting the previous one; combined `by`-derived spend plus an explicit spend line; template notes copied from another category that already had one.

Related errors


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