actualbudget/actual · error
Invalid adjustment percentage (${parsedTemplate.adjustment}%
Error message
Invalid adjustment percentage (${parsedTemplate.adjustment}%). Must be between -100% and 1000% What it means
Actual Budget's budget templates (the `#template` directives in category notes) support an `adjust` directive that can take a percentage. When the template is parsed during `getCategoriesWithTemplates`, the parsed adjustment value is validated: percentages are rejected if they are <= -100 (which would zero out or invert the category budget incoherently) or > 1000 (an implausible multiplier). The library throws this error to surface a malformed template directive in a category's notes rather than silently producing a wrong budget amount.
Source
Thrown at packages/loot-core/src/server/budget/template-notes.ts:122
const description =
descriptionLines.length > 0 ? descriptionLines.join('\n') : undefined;
descriptionLines = [];
try {
const parsedTemplate: Template = parse(trimmedLine);
// Validate schedule adjustments
if (
(parsedTemplate.type === 'average' ||
parsedTemplate.type === 'schedule') &&
parsedTemplate.adjustment !== undefined
) {
if (parsedTemplate.adjustmentType === 'percent') {
if (
parsedTemplate.adjustment <= -100 ||
parsedTemplate.adjustment > 1000
) {
throw new Error(
`Invalid adjustment percentage (${parsedTemplate.adjustment}%). Must be between -100% and 1000%`,
);
}
} else if (parsedTemplate.adjustmentType === 'fixed') {
//placeholder for potential validation of amount/fixed adjustments
}
}
parsedTemplates.push(
description ? { ...parsedTemplate, description } : parsedTemplate,
);
} catch (e: unknown) {
const errorTemplate: Template = {
type: 'error',
directive: 'error',
line,
error: (e as Error).message,
};View on GitHub (pinned to d4334cb6e6)
Solutions
- Open the category notes in the affected budget and fix the `#template adjust` directive so its percentage is in the valid range (-100% < p <= 1000%, exclusive of -100, inclusive of 1000).
- If you only need to drop a category's budget to zero, use `#template 0` or a fixed-amount adjust rather than `adjust -100%`.
- If the bad note came from a sync/restore, correct the note on the source device or delete the directive before re-syncing.
- Wrap the template-reading call in a try/catch during migration/import scripts so one bad note can be reported to the user with the category name instead of aborting the whole operation.
Example fix
// before (category note) #template adjust -100% // after #template adjust -50%
Defensive patterns
Strategy: validation
Validate before calling
function isValidAdjustPercent(pct) {
return typeof pct === 'number' && Number.isFinite(pct) && pct > -100 && pct <= 1000;
}
// scan category notes before syncing/importing:
// for each note, extract /#template\s+adjust\s+(-?[\d.]+)%/ and assert isValidAdjustPercent(parseFloat(m[1])) Type guard
function isWithinAdjustRange(value) {
return typeof value === 'number' && Number.isFinite(value) && value > -100 && value <= 1000;
} Prevention
- Keep `#template adjust` percentages in (-100%, 1000%]; remember -100% itself is rejected
- Use `#template 0` or fixed amounts when you want to zero a category instead of extreme percentages
- Lint/scan category notes for template directives in migration or template-sharing scripts
- Test templates in a scratch budget before syncing them to production budgets
When it happens
Trigger: Calling `getCategoriesWithTemplates` (directly or via `categoriesWithTemplates`/`categoryWithTemplates`) while one or more category notes contain a template directive like `#template adjust 2000%` (above 1000) or `#template adjust -150%` (at or below -100). Any budget action that reads templates with such a note triggers the throw.
Common situations: A user hand-edits category notes and typos an extra zero (e.g. `10000%` instead of `1000%`); a synced budget imported from another device contains a directive written before validation existed; a template-sharing workflow copies an extreme directive between budgets; a user misunderstands the allowed range and tries `-100%` expecting 'remove all budgeted amount'.
Related errors
- Error importing budget: ${result.error}
- Error importing budget: no budget was loaded
- Error exporting budget: ${result.error}
- Error exporting budget: no data was returned
- Query file must contain a JSON object
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/416c8a7065908659.
Report an issue: GitHub.