actualbudget/actual · error

Invalid BUDGET_QUERY dimension: ${dimension}

Error message

Invalid BUDGET_QUERY dimension: ${dimension}

What it means

fetchBudgetDimensionValueDirect validates the dimension argument of a BUDGET_QUERY against a fixed allowlist (including 'balance_start', 'balance_end', 'goal', etc.) after lowercasing. If the dimension is not in the set, it throws 'Invalid BUDGET_QUERY dimension: <dimension>'. This guards the direct budget fetch path from unknown or misspelled dimensions.

Source

Thrown at packages/desktop-client/src/hooks/useFormulaExecution.ts:646

}

// Helper: Evaluate budget dimension with already-extracted parameters (used by compositional BUDGET_QUERY)
async function fetchBudgetDimensionValueDirect(
  dimension: string,
  categoryIds: string[],
  startMonth: string,
  endMonth: string,
): Promise<number> {
  const allowed = new Set([
    'budgeted',
    'spent',
    'balance_start',
    'balance_end',
    'goal',
  ]);
  const dim = dimension.toLowerCase();
  if (!allowed.has(dim)) {
    throw new Error(`Invalid BUDGET_QUERY dimension: ${dimension}`);
  }

  const intervals = monthUtils.rangeInclusive(startMonth, endMonth);

  // Helper: sum a dimension across all months/categories
  const sumDimension = async (fieldPattern: string): Promise<number> => {
    let total = 0;
    for (const month of intervals) {
      const monthData = await getMonthBudgetData(month);
      for (const catId of categoryIds) {
        total += getMonthDataValue(monthData, fieldPattern, catId) as number;
      }
    }
    return total;
  };

  if (dim === 'budgeted') {
    return integerToAmount(await sumDimension('budget-{catId}'), 2);

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Check the spelling of the dimension against the supported list: the allowed set includes 'balance_start', 'balance_end', 'goal' (see the allowlist at useFormulaExecution.ts)
  2. Lowercase/trim the dimension input before calling, since matching is on the lowercased value
  3. Add the new dimension to the allowed set in fetchBudgetDimensionValueDirect if it is a legitimately supported dimension
  4. Validate dimension values at the formula parser layer to give earlier feedback

Example fix

// before
await prefetchBudgetQueries({ dimension: 'BALANCED' });
// after
const VALID = ['sumamount', 'budgeted', 'balance', 'balance_start', 'balance_end', 'goal'];
const dim = String(dimension).toLowerCase().trim();
if (!VALID.includes(dim)) {
  throw new Error(`Unsupported dimension, use one of: ${VALID.join(', ')}`);
}
await prefetchBudgetQueries({ dimension: dim });
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED = new Set(['sumamount','budgeted','balance','balance_start','balance_end','goal']);
const assertDimension = (d: string) => {
  const dim = String(d).toLowerCase().trim();
  if (!ALLOWED.has(dim)) throw new Error(`Invalid dimension ${d}; allowed: ${[...ALLOWED].join(', ')}`);
  return dim;
};

Try / catch

try {
  await prefetchBudgetQueries(args);
} catch (err) {
  if (err.message.startsWith('Invalid BUDGET_QUERY dimension')) {
    showError('Choose one of the supported budget dimensions');
  } else throw err;
}

Prevention

When it happens

Trigger: Calling prefetchBudgetQueries (or code that reaches fetchBudgetDimensionValueDirect) with a BUDGET_QUERY whose dimension string is misspelled, uses different casing with unexpected characters, or is a dimension only supported elsewhere but not in this direct path.

Common situations: Typos in a formula like BUDGET_QUERY(..., "balence"); copying a dimension name from another API that uses different naming; newly added dimensions not yet in the allowlist; passing a non-string such as a number.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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