actualbudget/actual · error
Tracking budget forecasts require a Tracking Budget file.
Error message
Tracking budget forecasts require a Tracking Budget file.
What it means
The forecast app (packages/loot-core/src/server/forecast/app.ts) only supports forecast runs against a Tracking Budget. generateForecast reads the 'budgetType' preference; if it is not exactly 'tracking', it throws this error before resolving forecast accounts. Forecasting depends on tracking-budget account structures and is intentionally unavailable for non-tracking (e.g. envelope/budget-type 'report') budgets.
Source
Thrown at packages/loot-core/src/server/forecast/app.ts:78
conditionsOp,
startDate,
endDate,
includeAccountlessSchedules,
source = 'schedules',
}: ForecastRequestParams): Promise<ForecastResult> {
const includeUnassigned = includeAccountlessSchedules ?? false;
const dateContext = buildForecastDateContext(startDate, endDate);
if (source === 'tracking-budget') {
const { value: budgetType = 'envelope' } =
(await db.first<Pick<db.DbPreference, 'value'>>(
`SELECT value FROM preferences WHERE id = ?`,
['budgetType'],
)) ?? {};
if (budgetType !== 'tracking') {
throw new Error(
'Tracking budget forecasts require a Tracking Budget file.',
);
}
const accounts = await resolveForecastAccounts({
accountIds: undefined,
plainConditions: [],
resolvedConditionsOp: 'and',
canRestrictAccounts: false,
});
const { dataPoints, lowestBalance } = projectTrackingBudgetForecast({
accounts,
dateContext,
});
return {
dataPoints,
lowestBalance,
forecastStartDate: dateContext.forecastStartDate,View on GitHub (pinned to d4334cb6e6)
Solutions
- Switch the budget to a Tracking Budget file (Settings > Show budget type / create or load a tracking budget) before running forecasts.
- Insert/set the preference if appropriate: UPDATE preferences SET value='tracking' WHERE id='budgetType' — only if the budget genuinely is a tracking budget.
- Guard automation: read the budgetType preference first and skip or branch forecast logic for non-tracking budgets.
- If budgetType is missing on a legacy file, set it explicitly to the correct type via the app rather than editing the DB by hand.
Example fix
// before
await aql.query('forecast-run'); // throws on non-tracking budgets
// after
const prefs = await aql.query('get-budget'); // or read preferences
if (budgetType !== 'tracking') {
console.warn('Forecasting requires a Tracking Budget; skipping.');
} else {
await aql.query('forecast-run');
} Defensive patterns
Strategy: validation
Validate before calling
// before invoking forecast, check the budget type preference
const budgetType = (await db.first('SELECT value FROM preferences WHERE id = ?', ['budgetType']))?.value;
if (budgetType !== 'tracking') {
throw new Error('Forecasting requires a Tracking Budget; load one first.');
} Type guard
function isTrackingBudget(budgetType: string | null | undefined): budgetType is 'tracking' {
return budgetType === 'tracking';
} Try / catch
try {
await aql.query('forecast-run');
} catch (e) {
if (e.message.includes('Tracking Budget')) {
// prompt the user to switch to / create a tracking budget
} else throw e;
} Prevention
- Check the budgetType preference before any forecast automation
- Document that forecasts are tracking-budget-only in plugin/script docs
- Handle legacy budgets with no budgetType preference explicitly instead of assuming a type
When it happens
Trigger: Calling the forecast endpoints (generateForecast, reached via 'forecast' mutators such as result/combinedResult/savingsOnlyResult) while the budget file's preferences row for id 'budgetType' is missing or set to anything other than 'tracking'.
Common situations: Running forecasts on an older budget file created before tracking budgets existed (no budgetType preference at all, so the query returns {} and ?? {} yields undefined !== 'tracking'); users switching budget types; plugins or scripts invoking forecast APIs on the wrong budget.
Related errors
- Error loading data into the spreadsheet.
- Unsupported summary type
- Unknown locale ${language}
- Failed to get server config.
- Unrecognized bank-sync provider: ${acctRow.account_sync_sour
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/800477a22892b827.
Report an issue: GitHub.