{"record":{"id":"277fb79e689dd461","repo":"actualbudget/actual","slug":"an-error-occurred-while-parsing-the-template","errorCode":null,"errorMessage":"An error occurred while parsing the template","messagePattern":"An error occurred while parsing the template","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/desktop-client/src/components/budget/goals/reducer.ts","lineNumber":86,"sourceCode":"      };\n    case 'refill':\n      return {\n        template,\n        displayType: 'refill',\n      };\n    case 'average':\n    case 'copy':\n      return {\n        template,\n        displayType: 'historical',\n      };\n    case 'goal':\n      return {\n        template,\n        displayType: 'goal',\n      };\n    case 'error':\n      throw new Error('An error occurred while parsing the template');\n    default:\n      throw new Error(\n        `Unknown template type: ${String(type satisfies undefined)}`,\n      );\n  }\n};\n\nconst changeType = (\n  prevState: ReducerState,\n  visualType: DisplayTemplateType,\n): ReducerState => {\n  switch (visualType) {\n    case 'limit':\n      if (prevState.template.type === 'limit') {\n        return prevState;\n      }\n      return {\n        displayType: visualType,","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/desktop-client/src/components/budget/goals/reducer.ts#L68-L104","documentation":"getInitialState switches on template.type; the 'error' type is what the template parser produces when category notes could not be parsed into a valid template. Encountering it here means an unparsed/error template reached the state-initialization path, so it throws a generic parse-failure message.","triggerScenarios":"Dispatching 'set-template' (or triggering mapTemplateTypesForUpdate merge) with a Template whose type is 'error' — i.e. the notes parser failed (bad template syntax like #template with invalid arguments) and the error object was passed on.","commonSituations":"Malformed template directives in category notes (e.g. #template up to with a bad amount or unsupported syntax); user edited notes by hand producing invalid template text; parser version differences after upgrades.","solutions":["Fix the template syntax in the category notes so the parser produces a valid template type","Check the parse output for a parse error message and correct the offending directive","If this should be handled gracefully, check for type === 'error' before calling getInitialState and show a user-facing parse error instead"],"exampleFix":"// before\ndispatch({ type: 'set-template', payload: parseTemplate(notes) });\n// after\nconst parsed = parseTemplate(notes);\nif (parsed.type === 'error') {\n  notify('The template in the category notes could not be parsed.');\n  return;\n}\ndispatch({ type: 'set-template', payload: parsed });","handlingStrategy":"validation","validationCode":"const parsed = parseTemplate(notes);\nif (parsed.type === 'error') {\n  notify('Category notes contain an invalid template.');\n  return;\n}\ndispatch({ type: 'set-template', payload: parsed });","typeGuard":"const isParsedTemplate = (t: Template): t is Exclude<Template, { type: 'error' }> =>\n  t.type !== 'error';","tryCatchPattern":"try {\n  dispatch({ type: 'set-template', payload: template });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('parsing the template')) {\n    notify('Fix the #template syntax in the category notes.');\n  } else throw e;\n}","preventionTips":["Validate template notes with the parser before editing","Surface the parser's error detail to users instead of the generic message","Test template syntax changes against the parser after upgrades"],"tags":["parsing","budget-templates","template-syntax","client-side"],"backgroundTag":"template-parse-error","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}