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
- Use one of the four valid values: 'all', 'inline', 'none', 'grouped'.
- Validate user-supplied option strings against isValidSplitsOption before building the query.
- 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
- Use a const literal union instead of raw strings for the option
- Trim/lowercase user-supplied options before validating
- Omit the option when the default behavior is acceptable
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
- Invalid "categories" option for category_groups: "${categori
- Field "${field}" does not exist in table "${tableName}"
- Invalid path: ${path}
- Path error: ${tableName} table does not exist
- Field not joinable on table ${tableName}: "${field}"
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/6eb774daa0192d8c.
Report an issue: GitHub.