actualbudget/actual · error · RuleError
parse-recur-date
parse-recur-date
Error message
parse-recur-date: ${e.message} What it means
`parseRecurDate` wraps any exception raised while parsing a recurring-date descriptor into a `RuleError` with code `parse-recur-date`. Recurring schedule date strings (RRULE-like objects) must conform to the expected descriptor shape; invalid frequency, interval, or sub-date values throw here.
Source
Thrown at packages/loot-core/src/server/rules/rule-utils.ts:235
}
}
export function parseRecurDate(desc) {
try {
const rules = recurConfigToRSchedule(desc);
return {
type: 'recur',
schedule: new RSchedule({
rrules: rules,
data: {
skipWeekend: desc.skipWeekend,
weekendSolve: desc.weekendSolveMode,
},
}),
};
} catch (e) {
throw new RuleError('parse-recur-date', e.message);
}
}
export function parseDateString(str) {
if (typeof str !== 'string') {
return null;
} else if (str.length === 10) {
// YYYY-MM-DD
if (!dateFns.isValid(dateFns.parseISO(str))) {
return null;
}
return { type: 'date', date: str };
} else if (str.length === 7) {
// YYYY-MM
if (!dateFns.isValid(dateFns.parseISO(str + '-01'))) {
return null;
}View on GitHub (pinned to d4334cb6e6)
Solutions
- Inspect `e.message` embedded in the error — it is the underlying parser message
- Validate the recurring descriptor: `frequency` in {daily, weekly, monthly, yearly}, positive `interval`, valid `start` date string
- Build schedules through the UI or a schedule-creation helper instead of hand-writing descriptors
- Fix the offending condition value in the schedule/rule data
Example fix
// before
{ field: 'date', op: 'isapprox', value: { frequency: 'biweekly', start: '2026-01-01' } }
// after
{ field: 'date', op: 'isapprox', value: { frequency: 'weekly', interval: 2, start: '2026-01-01' } } Defensive patterns
Strategy: validation
Validate before calling
function isValidRecurDescriptor(v) {
const freqs = ['daily', 'weekly', 'monthly', 'yearly'];
return (
v && typeof v === 'object' &&
freqs.includes(v.frequency) &&
(v.interval == null || (Number.isInteger(v.interval) && v.interval > 0)) &&
typeof v.start === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(v.start)
);
} Type guard
function isRecurringDateValue(v) {
return typeof v === 'object' && v !== null &&
typeof (v).frequency === 'string' &&
typeof (v).start === 'string';
} Try / catch
try {
const next = parseRecurDate(desc);
} catch (e) {
if (e.type === 'parse-recur-date') {
logger.error('Bad recurring descriptor', desc, e.message);
} else {
throw e;
}
} Prevention
- Validate recurring descriptors against the expected schema (frequency, interval, start) before use
- Use the UI or shared schedule helpers to build descriptors, never hand-write them
- Include the raw descriptor in error logs to diagnose parse failures
- Test descriptors with a known-good sample (e.g. {frequency:'monthly', start:'2026-01-01'})
When it happens
Trigger: Passing a malformed recurring date object to a date condition (e.g. `frequency` misspelled, missing `start`, invalid `interval`, bad nested `between`/`on` descriptors) which the underlying parser throws on.
Common situations: Hand-authoring recurring schedule conditions via the API; importing schedules from another tool; edited budget data where the `date` condition value was mangled.
Related errors
- Invalid start date format
- Invalid end date format
- Invalid date format provided
- Invalid date values provided
- Start date must be before or equal to end date.
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/cc231db75d7dfacd.
Report an issue: GitHub.