{"record":{"id":"31ecd28b42d60882","repo":"actualbudget/actual","slug":"weekly-limit-requires-a-start-date-yyyy-mm-dd","errorCode":null,"errorMessage":"Weekly limit requires a start date (YYYY-MM-DD)","messagePattern":"Weekly limit requires a start date \\(YYYY-MM-DD\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/server/budget/category-template-context.ts","lineNumber":601,"sourceCode":"          continue; // may not have a limit defined in the template\n        }\n      }\n\n      if (this.limitCheck) {\n        throw new Error('Only one `up to` allowed per category');\n      }\n\n      if (limitDef.period === 'daily') {\n        const numDays = monthUtils.differenceInCalendarDays(\n          monthUtils.addMonths(this.month, 1),\n          this.month,\n        );\n        this.limitAmount +=\n          amountToInteger(limitDef.amount, this.currency.decimalPlaces) *\n          numDays;\n      } else if (limitDef.period === 'weekly') {\n        if (!limitDef.start) {\n          throw new Error('Weekly limit requires a start date (YYYY-MM-DD)');\n        }\n        const nextMonth = monthUtils.nextMonth(this.month);\n        let week = limitDef.start;\n        const baseLimit = amountToInteger(\n          limitDef.amount,\n          this.currency.decimalPlaces,\n        );\n        while (week < nextMonth) {\n          if (week >= this.month) {\n            this.limitAmount += baseLimit;\n          }\n          week = monthUtils.addWeeks(week, 1);\n        }\n      } else if (limitDef.period === 'monthly') {\n        this.limitAmount = amountToInteger(\n          limitDef.amount,\n          this.currency.decimalPlaces,\n        );","sourceCodeStart":583,"sourceCodeEnd":619,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/server/budget/category-template-context.ts#L583-L619","documentation":"A weekly limit (`up to ... weekly`) must include an explicit start date in YYYY-MM-DD format so the engine knows where week boundaries fall. `checkLimit` throws when `limitDef.period === 'weekly'` but `limitDef.start` is missing.","triggerScenarios":"A template like `#template up to 100 weekly` (no `starting <date>` clause) is processed by `checkLimit` during category context construction — the weekly period requires `start` to compute aligned week windows across the budget month.","commonSituations":"Writing a weekly limit template without the required `starting YYYY-MM-DD` clause; hand-editing templates after reading older docs; converting a monthly limit template to weekly by only changing the period keyword.","solutions":["Add the `starting YYYY-MM-DD` clause to the weekly limit, e.g. `#template up to 100 weekly starting 2024-01-01`","Or switch the limit to a period that does not require a start date (monthly, daily)"],"exampleFix":"// before\n#template up to 100 weekly\n// after\n#template up to 100 weekly starting 2024-01-01","handlingStrategy":"validation","validationCode":"if (/weekly/.test(line) && !/starting \\d{4}-\\d{2}-\\d{2}/.test(line)) throw new Error('weekly limit needs: starting YYYY-MM-DD');","typeGuard":"function hasWeeklyStart(limitDef) {\n  return limitDef.period !== 'weekly' || typeof limitDef.start === 'string' && /^\\d{4}-\\d{2}-\\d{2}$/.test(limitDef.start);\n}","tryCatchPattern":"try {\n  await init();\n} catch (e) {\n  if (e.message.includes('Weekly limit requires a start date')) {\n    // append `starting YYYY-MM-DD` to the weekly limit line\n  } else throw e;\n}","preventionTips":["Always pair `weekly` with `starting YYYY-MM-DD` in limit templates","Pick a start date aligned with your pay/week cycle","Test new limit templates on a scratch budget first"],"tags":["goal-templates","limit","weekly","template-syntax"],"backgroundTag":"missing-required-argument","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}