actualbudget/actual · error
Invalid "categories" option for category_groups: "${categori
Error message
Invalid "categories" option for category_groups: "${categoriesOption}" What it means
execCategoryGroups validates the 'categories' table option for category_groups queries, which must be 'all' or 'none'. Any other value is rejected before SQL execution.
Source
Thrown at packages/loot-core/src/server/aql/schema/executors.ts:269
}
// Category groups executor
type CategoriesOption = 'all' | 'none';
async function execCategoryGroups(
compilerState: CompilerState,
queryState: QueryState,
sqlPieces: SqlPieces,
params: (string | number)[],
outputTypes: OutputTypes,
) {
const tableOptions = queryState.tableOptions || {};
const categoriesOption = tableOptions.categories
? (tableOptions.categories as string)
: 'all';
if (!isValidCategoriesOption(categoriesOption)) {
throw new Error(
`Invalid "categories" option for category_groups: "${categoriesOption}"`,
);
}
if (categoriesOption !== 'none') {
return execCategoryGroupsWithCategories(
compilerState,
queryState,
sqlPieces,
params,
categoriesOption,
outputTypes,
);
}
return execCategoryGroupsBasic(
compilerState,
queryState,
sqlPieces,View on GitHub (pinned to d4334cb6e6)
Solutions
- Use 'all' or 'none' for the categories option.
- Validate the option before constructing the query.
- Omit the option to get the default 'all' behavior.
Example fix
// before
q('category_groups', { categories: 'exclude-none' });
// after
q('category_groups', { categories: 'all' }); Defensive patterns
Strategy: validation
Validate before calling
const CATEGORIES_OPTIONS = ['all','none'];
function validateCategoriesOption(o) {
const v = o ?? 'all';
if (!CATEGORIES_OPTIONS.includes(v)) throw new Error(`categories must be ${CATEGORIES_OPTIONS.join(' or ')}`);
} Type guard
function isCategoriesOption(v: unknown): v is 'all'|'none' {
return v === 'all' || v === 'none';
} Try / catch
try {
return await q('category_groups', { categories: opt }).select('*').execute();
} catch (e) {
if (e.message.includes('Invalid "categories" option')) {
return q('category_groups').select('*').execute();
}
throw e;
} Prevention
- Do not reuse the transactions 'splits' values for category_groups queries
- Validate any config-driven option strings at load time
- Prefer omitting the option to get 'all' by default
When it happens
Trigger: q('category_groups', { categories: 'only' }) or any string other than 'all'/'none' (default is 'all').
Common situations: Copying the 'splits' option style from transactions queries, typos, or passing config-driven strings without validation.
Related errors
- Invalid "splits" option for transactions: "${splitType}"
- 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/7b7f39b5d6d97e2d.
Report an issue: GitHub.