{"record":{"id":"ddf46846450350b4","repo":"actualbudget/actual","slug":"unitialised-context-method-called-ontogglesummary-ddf468","errorCode":null,"errorMessage":"Unitialised context method called: onToggleSummaryCollapse","messagePattern":"Unitialised context method called: onToggleSummaryCollapse","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/desktop-client/src/components/budget/tracking/TrackingBudgetContext.tsx","lineNumber":19,"sourceCode":"import React, { createContext, useContext } from 'react';\nimport type { ReactNode } from 'react';\n\nimport * as monthUtils from '@actual-app/core/shared/months';\n\ntype TrackingBudgetContextDefinition = {\n  summaryCollapsed: boolean;\n  onBudgetAction: (month: string, action: string, arg?: unknown) => void;\n  onToggleSummaryCollapse: () => void;\n  currentMonth: string;\n};\n\nconst TrackingBudgetContext = createContext<TrackingBudgetContextDefinition>({\n  summaryCollapsed: false,\n  onBudgetAction: () => {\n    throw new Error('Unitialised context method called: onBudgetAction');\n  },\n  onToggleSummaryCollapse: () => {\n    throw new Error(\n      'Unitialised context method called: onToggleSummaryCollapse',\n    );\n  },\n  currentMonth: 'unknown',\n});\n\ntype TrackingBudgetProviderProps = Omit<\n  TrackingBudgetContextDefinition,\n  'currentMonth'\n> & {\n  children: ReactNode;\n};\nexport function TrackingBudgetProvider({\n  summaryCollapsed,\n  onBudgetAction,\n  onToggleSummaryCollapse,\n  children,\n}: TrackingBudgetProviderProps) {","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/desktop-client/src/components/budget/tracking/TrackingBudgetContext.tsx#L1-L37","documentation":"Same family as error 426 but for the second stub in TrackingBudgetContext's default value: onToggleSummaryCollapse throws because the context was never provided with a real implementation. It fires when a consumer invokes the summary-collapse toggle while only the createContext defaults are in scope.","triggerScenarios":"Clicking the collapse/expand summary toggle in a component that consumed TrackingBudgetContext without a TrackingBudgetContext.Provider ancestor supplying onToggleSummaryCollapse.","commonSituations":"Component reused outside the tracking budget page; storybook/test render without the provider; provider value built by spreading partial state that omits onToggleSummaryCollapse after a refactor.","solutions":["Mount TrackingBudgetContext.Provider above the consumer with a real onToggleSummaryCollapse callback.","Check that the provider's value object actually includes onToggleSummaryCollapse (not just onBudgetAction).","Wrap isolated renders (Storybook, tests) with the provider or a test harness that supplies both methods."],"exampleFix":"// before\nrender(<BudgetSummary />); // uses context default -> throws on toggle\n\n// after\nrender(\n  <TrackingBudgetContext.Provider value={{ summaryCollapsed: false, onBudgetAction: vi.fn(), onToggleSummaryCollapse: vi.fn(), currentMonth: '2026-08' }}>\n    <BudgetSummary />\n  </TrackingBudgetContext.Provider>\n);","handlingStrategy":"try-catch","validationCode":"const ctx = useContext(TrackingBudgetContext);\nif (typeof ctx.onToggleSummaryCollapse !== 'function' || isDefaultStub(ctx.onToggleSummaryCollapse)) {\n  throw new Error('TrackingBudgetContext provider missing onToggleSummaryCollapse');\n}","typeGuard":"function canToggleSummary(ctx: TrackingBudgetContextDefinition): boolean {\n  return typeof ctx.onToggleSummaryCollapse === 'function';\n}","tryCatchPattern":"try {\n  onToggleSummaryCollapse();\n} catch (err) {\n  if (err instanceof Error && err.message.includes('Unitialised context method called: onToggleSummaryCollapse')) {\n    logger.warn('Summary collapse unavailable: TrackingBudgetContext not provided');\n  } else {\n    throw err;\n  }\n}","preventionTips":["Ensure the provider value object includes both onBudgetAction and onToggleSummaryCollapse.","Gate collapse UI behind the same layout that provides the context.","Add a render-time check in the consuming hook to fail fast with a clear message."],"tags":["react","react-context","missing-provider","budget"],"backgroundTag":"context-used-outside-provider","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}