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.

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)

Solutions

  1. Always include a non-null name in the fields object (use the current group's name if only toggling other attributes)
  2. Fetch the group first and spread it: api.accountGroupUpdate(id, { ...existing, name: existing.name })
  3. 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

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 field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


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