{"record":{"id":"bc83064ee26113b3","repo":"actualbudget/actual","slug":"schedule-t-name-t-scheduleid-does-not-exist","errorCode":null,"errorMessage":"Schedule ${t.name ?? t.scheduleId} does not exist","messagePattern":"Schedule (.+?) does not exist","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/server/budget/category-template-context.ts","lineNumber":492,"sourceCode":"  ) {\n    if (\n      templates.filter(t => t.type === 'schedule' || t.type === 'by').length ===\n      0\n    ) {\n      return;\n    }\n    //check schedule existence (prefer scheduleId, fall back to name)\n    const activeSchedules = await getActiveSchedules();\n    const scheduleIds = new Set(activeSchedules.map(s => s.id));\n    const scheduleNames = new Set(\n      activeSchedules.map(s => s.name?.trim()).filter(Boolean),\n    );\n    templates\n      .filter(t => t.type === 'schedule')\n      .forEach(t => {\n        if (t.scheduleId) {\n          if (!scheduleIds.has(t.scheduleId)) {\n            throw new Error(\n              `Schedule ${t.name ?? t.scheduleId} does not exist`,\n            );\n          }\n        } else if (t.name) {\n          if (!scheduleNames.has(t.name.trim())) {\n            throw new Error(`Schedule ${t.name.trim()} does not exist`);\n          }\n        } else {\n          throw new Error('Schedule template has no scheduleId or name');\n        }\n      });\n    //find lowest priority\n    const lowestPriority = Math.min(\n      ...templates\n        .filter(t => t.type === 'schedule' || t.type === 'by')\n        .map(t => t.priority),\n    );\n    //warn if priority needs fixed","sourceCodeStart":474,"sourceCodeEnd":510,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/server/budget/category-template-context.ts#L474-L510","documentation":"The category template system resolves 'schedule' templates against the set of schedules that exist in the budget. A template referencing a schedule id or name not found in the budget throws during context initialization.","triggerScenarios":"A category note contains a directive like '#template schedule <name>' where <name> does not match any schedule (deleted schedule, renamed schedule, or schedule from another budget).","commonSituations":"Deleting or renaming a schedule after writing template directives in category notes; typos in schedule names; copying budget templates between budgets that have different schedules.","solutions":["Recreate the missing schedule or update the category template note to reference an existing schedule name/id.","List existing schedules (q('schedules').select('*')) and match template references against them.","Use schedule ids instead of names for stability across renames."],"exampleFix":"// before\n// category note: #template schedule Electric Bill   (schedule was deleted)\n// after\n// recreate the schedule, or update the note to:\n// #template schedule Electric Bill 2024   (existing schedule name)","handlingStrategy":"validation","validationCode":"const schedules = await q('schedules').select('name').execute();\nconst names = new Set(schedules.map(s => s.name.trim()));\nif (!names.has(templateScheduleName)) throw new Error(`Schedule \"${templateScheduleName}\" not found in this budget`);","typeGuard":null,"tryCatchPattern":"try {\n  await app.runBudgetTemplates();\n} catch (e) {\n  if (e.message.includes('does not exist') && e.message.includes('Schedule')) {\n    console.error('A category note references a missing schedule:', e.message);\n  } else throw e;\n}","preventionTips":["When deleting a schedule, search category notes for its references first","Reference schedules by id rather than name in templates","Recheck template directives after importing/copying budgets"],"tags":["budget-templates","schedule","not-found"],"backgroundTag":"schedule-not-found","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}