{"record":{"id":"d34f4db6e24cd9b0","repo":"actualbudget/actual","slug":"invalid-recurring-date-config","errorCode":null,"errorMessage":"Invalid recurring date config","messagePattern":"Invalid recurring date config","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/shared/schedules.ts","lineNumber":251,"sourceCode":"      if (config.patterns && config.patterns.length > 0) {\n        const days = config.patterns.filter(p => p.type === 'day');\n        const dayNames = config.patterns.filter(p => p.type !== 'day');\n\n        return [\n          days.length > 0 && { ...base, byDayOfMonth: days.map(p => p.value) },\n          dayNames.length > 0 && {\n            ...base,\n            byDayOfWeek: dayNames.map(p => [abbrevDay(p.type), p.value]),\n          },\n        ].filter(Boolean);\n      } else {\n        // Nothing to do\n        return [base];\n      }\n    case 'yearly':\n      return [base];\n    default:\n      throw new Error('Invalid recurring date config');\n  }\n}\n\nexport function extractScheduleConds(conditions) {\n  return {\n    payee:\n      conditions.find(cond => cond.op === 'is' && cond.field === 'payee') ||\n      conditions.find(\n        cond => cond.op === 'is' && cond.field === 'description',\n      ) ||\n      null,\n    account:\n      conditions.find(cond => cond.op === 'is' && cond.field === 'account') ||\n      conditions.find(cond => cond.op === 'is' && cond.field === 'acct') ||\n      null,\n    amount:\n      conditions.find(\n        cond =>","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/shared/schedules.ts#L233-L269","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n{ frequency: 'biweekly', start: '2024-01-01' }\n// after\n{ frequency: 'weekly', interval: 2, start: '2024-01-01' }","handlingStrategy":"validation","validationCode":"const VALID = ['daily','weekly','monthly','yearly'];\nfunction isValidRecurConfig(cfg) {\n  return cfg && typeof cfg.frequency === 'string' && VALID.includes(cfg.frequency);\n}\nif (!isValidRecurConfig(cond.value)) throw new Error('Bad frequency before saving schedule');","typeGuard":"const VALID = ['daily','weekly','monthly','yearly'] as const;\ntype Frequency = typeof VALID[number];\nfunction isFrequency(f: unknown): f is Frequency {\n  return typeof f === 'string' && (VALID as readonly string[]).includes(f);\n}","tryCatchPattern":"try {\n  const rdates = recurConfigToRSchedule(cond.value);\n} catch (e) {\n  if (e.message === 'Invalid recurring date config') {\n    logger.log('Skipping schedule with unsupported frequency', cond.value);\n    rdates = null; // degrade gracefully\n  } else throw e;\n}","preventionTips":["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"],"tags":["schedules","validation","data-corruption"],"backgroundTag":"invalid-config-value","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}