actualbudget/actual · error
Invalid recurring date config
Error message
Invalid recurring date config
What it means
recurConfigToRSchedule converts a schedule's recurring-date configuration into an RSchedule rule. The config's frequency field must be one of the supported values (daily, weekly, monthly, yearly); anything else falls to the default branch and throws this generic Error.
Source
Thrown at packages/loot-core/src/shared/schedules.ts:251
if (config.patterns && config.patterns.length > 0) {
const days = config.patterns.filter(p => p.type === 'day');
const dayNames = config.patterns.filter(p => p.type !== 'day');
return [
days.length > 0 && { ...base, byDayOfMonth: days.map(p => p.value) },
dayNames.length > 0 && {
...base,
byDayOfWeek: dayNames.map(p => [abbrevDay(p.type), p.value]),
},
].filter(Boolean);
} else {
// Nothing to do
return [base];
}
case 'yearly':
return [base];
default:
throw new Error('Invalid recurring date config');
}
}
export function extractScheduleConds(conditions) {
return {
payee:
conditions.find(cond => cond.op === 'is' && cond.field === 'payee') ||
conditions.find(
cond => cond.op === 'is' && cond.field === 'description',
) ||
null,
account:
conditions.find(cond => cond.op === 'is' && cond.field === 'account') ||
conditions.find(cond => cond.op === 'is' && cond.field === 'acct') ||
null,
amount:
conditions.find(
cond =>View on GitHub (pinned to d4334cb6e6)
Solutions
- Inspect the schedule's conditions in the DB/rules and correct the frequency to one of daily|weekly|monthly|yearly
- Delete and recreate the broken schedule from the UI
- Validate the recurring config before persisting it (reject unknown frequencies at input time)
- Check for version mismatch between the tool that created the schedule and the current app version
Example fix
// before
{ frequency: 'biweekly', start: '2024-01-01' }
// after
{ frequency: 'weekly', interval: 2, start: '2024-01-01' } Defensive patterns
Strategy: validation
Validate before calling
const VALID = ['daily','weekly','monthly','yearly'];
function isValidRecurConfig(cfg) {
return cfg && typeof cfg.frequency === 'string' && VALID.includes(cfg.frequency);
}
if (!isValidRecurConfig(cond.value)) throw new Error('Bad frequency before saving schedule'); Type guard
const VALID = ['daily','weekly','monthly','yearly'] as const;
type Frequency = typeof VALID[number];
function isFrequency(f: unknown): f is Frequency {
return typeof f === 'string' && (VALID as readonly string[]).includes(f);
} Try / catch
try {
const rdates = recurConfigToRSchedule(cond.value);
} catch (e) {
if (e.message === 'Invalid recurring date config') {
logger.log('Skipping schedule with unsupported frequency', cond.value);
rdates = null; // degrade gracefully
} else throw e;
} Prevention
- Validate frequency at schedule-creation input time
- Don't hand-edit schedule rule JSON in the DB
- Test schedules after restoring data from other tools or older versions
When it happens
Trigger: Reading a schedule whose recurring_date/condition object has a frequency value outside the supported set — e.g. corrupted schedule data, a schedule serialized by a newer/older version, or hand-edited rule JSON passed into rules/schedule APIs.
Common situations: Restoring budgets from other tools or manual DB edits that wrote an unsupported frequency; version drift where an old client saved a frequency the current code no longer maps; programming errors building a schedule config programmatically.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- There is already a schedule named: ${newName}
- Field ${typedKey} is system-managed and not user-editable.
- Invalid amount operator: ${String(value)}. Expected: is, isa
- Date can not be found. Schedules can not be created without
- throw Error(errorMsg)
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/d34f4db6e24cd9b0.
Report an issue: GitHub.