actualbudget/actual · error

Invalid "splits" option for transactions: "${splitType}"

Error message

Invalid "splits" option for transactions: "${splitType}"

What it means

execTransactions validates the optional 'splits' table option, which must be one of 'all' | 'inline' | 'none' | 'grouped'. Any other value passed when constructing the query is rejected before SQL runs.

Source

Thrown at packages/loot-core/src/server/aql/schema/executors.ts:55

// q('transactions', { splits: "grouped" }).select({ $count: 'id' })
//
// The first will return the count of non-split and child
// transactions, and the second will return the count of all parent
// (or non-split) transactions

function execTransactions(
  compilerState: CompilerState,
  queryState: QueryState,
  sqlPieces: SqlPieces,
  params: (string | number)[],
  outputTypes: OutputTypes,
) {
  const tableOptions = queryState.tableOptions || {};
  const splitType = tableOptions.splits
    ? (tableOptions.splits as string)
    : 'inline';
  if (!isValidSplitsOption(splitType)) {
    throw new Error(`Invalid "splits" option for transactions: "${splitType}"`);
  }

  if (splitType === 'all' || splitType === 'inline' || splitType === 'none') {
    return execTransactionsBasic(
      compilerState,
      queryState,
      sqlPieces,
      params,
      splitType,
      outputTypes,
    );
  } else if (splitType === 'grouped') {
    return execTransactionsGrouped(
      compilerState,
      queryState,
      sqlPieces,
      params,
      outputTypes,

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Use one of the four valid values: 'all', 'inline', 'none', 'grouped'.
  2. Validate user-supplied option strings against isValidSplitsOption before building the query.
  3. Omit the option entirely if you want the default 'inline' behavior.

Example fix

// before
q('transactions', { splits: 'group' });
// after
q('transactions', { splits: 'grouped' });
Defensive patterns

Strategy: validation

Validate before calling

const SPLITS_OPTIONS = ['all','inline','none','grouped'];
function validateSplits(o) { if (o && !SPLITS_OPTIONS.includes(o)) throw new Error(`splits must be one of ${SPLITS_OPTIONS.join(', ')}`); }

Type guard

function isSplitsOption(v: unknown): v is 'all'|'inline'|'none'|'grouped' {
  return typeof v === 'string' && ['all','inline','none','grouped'].includes(v);
}

Try / catch

try {
  return await q('transactions', { splits }).select('*').execute();
} catch (e) {
  if (e.message.includes('Invalid "splits" option')) {
    return q('transactions').select('*').execute(); // fallback to default
  }
  throw e;
}

Prevention

When it happens

Trigger: q('transactions', { splits: 'grouped ' }) or { splits: 'parent' } — any string not exactly matching a valid option.

Common situations: Typos, capitalization ('Grouped'), trailing whitespace, or passing user/CLI supplied strings without validation.

Related errors


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