actualbudget/actual · error · APIError
Failed updating the rule
Error message
Failed updating the rule
What it means
api.updateRule() pushes the converted rule through the internal rule-update handler. When that handler returns { error } (rule not found or invalid content), the API throws this APIError carrying the underlying error.
Source
Thrown at packages/loot-core/src/server/api.ts:911
handlers['api/rule-create'] = withMutation(async function ({ rule }) {
checkFileOpen();
const addedRule = await handlers['rule-add'](ruleModel.fromExternal(rule));
if ('error' in addedRule) {
throw APIError('Failed creating a new rule', addedRule.error);
}
return addedRule;
});
handlers['api/rule-update'] = withMutation(async function ({ rule }) {
checkFileOpen();
const updatedRule = await handlers['rule-update'](
ruleModel.fromExternal(rule),
);
if ('error' in updatedRule) {
throw APIError('Failed updating the rule', updatedRule.error);
}
return updatedRule;
});
handlers['api/rule-delete'] = withMutation(async function (id) {
checkFileOpen();
return handlers['rule-delete'](id);
});
handlers['api/schedules-get'] = async function () {
checkFileOpen();
const { data } = await aqlQuery(q('schedules').select('*'));
const schedules = data as ScheduleEntity[];
return schedules.map(schedule => scheduleModel.toExternal(schedule));
};
handlers['api/schedule-create'] = withMutation(async function (View on GitHub (pinned to d4334cb6e6)
Solutions
- Confirm the rule id exists via api.getRules() before updating
- Check the APIError's cause for the underlying validation failure and correct the conditions/actions
- Re-fetch the rule with a fresh get and modify its fields rather than reusing cached payloads
Example fix
// before
await api.updateRule(cachedRule);
// after
const rules = await api.getRules();
const fresh = rules.find(r => r.id === cachedRule.id);
if (fresh) await api.updateRule({ ...fresh, ...changes }); Defensive patterns
Strategy: try-catch
Validate before calling
const parsed = ruleModel.fromExternal(rule);
const res = await handlers['rule-update'](parsed);
if ('error' in res) preflightCheck(res.error); Type guard
function isRuleError(r) {
return r != null && typeof r === 'object' && 'error' in r;
} Try / catch
const updated = await ruleUpdate(rule);
if (isRuleError(updated)) {
throw new APIError('Failed updating the rule', updated.error);
} Prevention
- Confirm rule existence before update
- Reuse the same validator as creation for conditions/actions
- Log the wrapped cause with the rule id
When it happens
Trigger: Calling api.updateRule(rule) with a rule id that doesn't exist in the budget, or with conditions/actions failing validation (unknown fields, bad operators, empty actions).
Common situations: Updating a rule from a stale id after the budget was re-imported/rolled back; mutating a rule fetched in a previous session before a file switch; same validation pitfalls as rule creation.
Related errors
- Failed creating a new rule
- Unknown payee name normalization: ${String(normalization)}
- `date` is required when adding a transaction
- Amount is invalid, must be an integer: ${trans.amount}
- There is already a filter named ${item.name}
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/f8263c985513baff.
Report an issue: GitHub.