actualbudget/actual · error · APIError
Failed creating a new rule
Error message
Failed creating a new rule
What it means
api.createRule() delegates to the internal rule-add handler, which validates the rule (conditions, actions, condition structure). If the internal handler returns { error }, the API wraps it in this APIError with the original error attached.
Source
Thrown at packages/loot-core/src/server/api.ts:898
return handlers['payees-get-nearby']({ latitude, longitude, maxDistance });
};
handlers['api/rules-get'] = async function () {
checkFileOpen();
return handlers['rules-get']();
};
handlers['api/payee-rules-get'] = async function ({ id }) {
checkFileOpen();
return handlers['payees-get-rules']({ id });
};
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;
});
View on GitHub (pinned to d4334cb6e6)
Solutions
- Inspect the attached addedRule.error (the APIError's cause) for the underlying validation message
- Build the rule object with a valid conditionOp/conditions shape per docs — verify field names and operator/value compatibility
- Test the same rule in the UI Rules editor; if the UI rejects it too, fix the rule, not the API call
Example fix
// before
await api.createRule({ conditions: [{ field: 'payee_name', op: 'contains', value: 123 }] });
// after
await api.createRule({ conditions: [{ field: 'payee_name', op: 'contains', value: 'Store' }], actions: [{ field: 'category', value: 'Groceries' }], operation: 'and' }); Defensive patterns
Strategy: try-catch
Validate before calling
const parsed = ruleModel.fromExternal(rule);
const res = await handlers['rule-add'](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 added = await ruleAdd(rule);
if (isRuleError(added)) {
throw new APIError('Failed creating a new rule', added.error);
} Prevention
- Validate rule shape against the current RuleEntity model before insert
- Surface the wrapped cause to callers for debugging
- Add fixtures covering each operator/field combo in CI
When it happens
Trigger: Calling api.createRule(rule) with a rule whose conditions/actions reference unknown fields, invalid operators (e.g. wrong value type for the operator), or a malformed conditions object.
Common situations: Hand-constructed rule payloads in scripts; rules exported from an older Actual version with operators no longer supported; typos in field names like 'payee' vs 'payee_name'.
Related errors
- Failed updating the 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/c29d1ea31fefadc2.
Report an issue: GitHub.