actualbudget/actual · error · APIError
Account group name is required
Error message
Account group name is required
What it means
api.accountGroupUpdate() converts the provided fields via the account-group model's fromExternal() and requires a group name. If the resulting group.name is null/undefined (i.e. no name field was supplied), the update would blank or invalidate the group, so the API throws this APIError.
Solutions
- Always include a non-null name in the fields object (use the current group's name if only toggling other attributes)
- Fetch the group first and spread it: api.accountGroupUpdate(id, { ...existing, name: existing.name })
- Validate fields.name is a non-empty string before calling
Example fix
// before
await api.accountGroupUpdate(id, { cash: 1000 });
// after
const group = await api.accountGroupGet(id);
await api.accountGroupUpdate(id, { ...group, cash: 1000, name: group.name }); Defensive patterns
Strategy: validation
Validate before calling
const group = accountGroupModel.fromExternal(fields);
if (group.name == null) throw APIError('Account group name is required'); Type guard
function hasValidName(g) {
return g.name != null && String(g.name).length > 0;
} Try / catch
try {
await updateAccountGroup(args);
} catch (e) {
if (/name is required/.test(e.message)) {
throw new UserInputError('name is required for account groups');
}
throw e;
} Prevention
- Make name mandatory in the external input schema (zod/JSON schema)
- Require full-group payloads for updates
- Reject empty names at the boundary
When it happens
Trigger: Calling api.accountGroupUpdate(id, fields) where fields omits 'name' or passes name: null/undefined.
Common situations: Partially-patch-style updates where the caller assumes only changed fields are needed; forms that submit empty names; destructuring/serialization dropping the name key.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Amount is invalid, must be an integer
- Amount to hold needs to be greater than 0
- balance is non-zero: transferAccountId is required
- Conditions are required
- Creating a category: groupId is required
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/7abc9b75701b3851.
Report an issue: GitHub.
Appendix: source
Thrown at packages/loot-core/src/server/api.ts:692
handlers['api/account-groups-get'] = async function () {
checkFileOpen();
const groups = await handlers['account-groups-get']();
return groups.map(group => accountGroupModel.toExternal(group));
};
handlers['api/account-group-create'] = withMutation(async function ({ group }) {
checkFileOpen();
return handlers['account-group-create']({ name: group.name });
});
handlers['api/account-group-update'] = withMutation(async function ({
id,
fields,
}) {
checkFileOpen();
const group = accountGroupModel.fromExternal(fields);
if (group.name == null) {
throw APIError('Account group name is required');
}
return handlers['account-group-update']({ id, name: group.name });
});
handlers['api/account-group-delete'] = withMutation(async function ({ id }) {
checkFileOpen();
await handlers['account-group-delete']({ id });
});
handlers['api/categories-get'] = async function ({
hidden,
}: { hidden?: boolean } = {}) {
checkFileOpen();
const result = await handlers['get-categories']({ hidden });
return result.list.map(category => categoryModel.toExternal(category));
};
handlers['api/category-groups-get'] = async function ({View on GitHub (pinned to d4334cb6e6)