actualbudget/actual · error

Only one #goal is allowed per category

Error message

Only one #goal is allowed per category

What it means

A category may have at most one `#goal` template. `checkGoal` (called during CategoryTemplateContext construction) throws when `this.goals` holds more than one goal for the same category, because a single category cannot have conflicting goal definitions.

Source

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

        } 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

  static runSimple(
    template: SimpleTemplate,
    templateContext: CategoryTemplateContext,
  ): number {
    if (template.monthly != null) {

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Remove or update the extra `#template goal ...` line so only one goal remains per category
  2. Combine the amounts into a single goal if both targets are intended

Example fix

// before
#template goal 500
#template goal 1000
// after
#template goal 1000
Defensive patterns

Strategy: validation

Validate before calling

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

Try / catch

try {
  await init();
} catch (e) {
  if (e.message === 'Only one #goal is allowed per category') {
    // keep one #template goal line and delete the rest
  } else throw e;
}

Prevention

When it happens

Trigger: Two or more `#template goal <amount>` lines exist for the same category in the same month, e.g. `#template goal 500` plus another `#template goal 1000` in the category note.

Common situations: Editing a goal amount by adding a new line instead of updating the existing one; leftover goal line from a previous month's note still applying; pasting templates from another category.

Related errors


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