{"record":{"id":"4a93123540a4e4cb","repo":"actualbudget/actual","slug":"unitialised-context-method-called-onbudgetaction","errorCode":null,"errorMessage":"Unitialised context method called: onBudgetAction","messagePattern":"Unitialised context method called: onBudgetAction","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetContext.tsx","lineNumber":16,"sourceCode":"import React, { createContext, useContext } from 'react';\nimport type { ReactNode } from 'react';\n\nimport * as monthUtils from '@actual-app/core/shared/months';\n\ntype EnvelopeBudgetContextDefinition = {\n  summaryCollapsed: boolean;\n  onBudgetAction: (month: string, action: string, arg?: unknown) => void;\n  onToggleSummaryCollapse: () => void;\n  currentMonth: string;\n};\n\nconst EnvelopeBudgetContext = createContext<EnvelopeBudgetContextDefinition>({\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 EnvelopeBudgetProviderProps = Omit<\n  EnvelopeBudgetContextDefinition,\n  'currentMonth'\n> & {\n  children: ReactNode;\n};\nexport function EnvelopeBudgetProvider({\n  summaryCollapsed,\n  onBudgetAction,","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetContext.tsx#L1-L34","documentation":"EnvelopeBudgetContext's default createContext value contains a stub onBudgetAction that throws, mirroring the ServerContext pattern: consumers must be rendered under the EnvelopeBudgetContext.Provider which supplies the real dispatch-to-budget handler. Hitting the stub means no provider is present above the caller.","triggerScenarios":"Invoking onBudgetAction(month, action) from a component (or test/story render) that is not inside <EnvelopeBudgetContext.Provider>, e.g. envelope budget widgets rendered standalone.","commonSituations":"Unit tests of EnvelopeBudgetCell/BalanceCell without the provider wrapper; rendering budget subcomponents in isolation; moving a component above the provider during a refactor.","solutions":["Wrap the consumer in the EnvelopeBudgetContext.Provider (as the envelope budget page does) supplying onBudgetAction and the other fields.","In tests/stories, provide a mock context value: onBudgetAction: vi.fn(), onToggleSummaryCollapse: vi.fn(), currentMonth: '2026-01'.","Assert provider presence early by consuming currentMonth in dev — the sentinel 'unknown' value indicates the stub context is active."],"exampleFix":"// before (test)\nrender(<EnvelopeBudgetCell month=\"2026-01\" />);\n\n// after\nrender(\n  <EnvelopeBudgetContext.Provider value={{ summaryCollapsed: false, onBudgetAction: vi.fn(), onToggleSummaryCollapse: vi.fn(), currentMonth: '2026-01' }}>\n    <EnvelopeBudgetCell month=\"2026-01\" />\n  </EnvelopeBudgetContext.Provider>\n);","handlingStrategy":"try-catch","validationCode":"const ctx = useContext(EnvelopeBudgetContext);\nconst isProviderReady = ctx.currentMonth !== 'unknown' && typeof ctx.onBudgetAction === 'function';\nif (!isProviderReady) throw new Error('EnvelopeBudgetContext.Provider missing');","typeGuard":"function hasEnvelopeBudgetContext(ctx: EnvelopeBudgetContextDefinition): boolean {\n  return ctx.currentMonth !== 'unknown' && typeof ctx.onBudgetAction === 'function';\n}","tryCatchPattern":"try {\n  onBudgetAction(month, { type: 'budget-amount' });\n} catch (e) {\n  if (String(e.message).includes('Unitialised context method')) {\n    // provider absent: skip or route back to budget page\n  } else throw e;\n}","preventionTips":["Render all envelope budget cells under EnvelopeBudgetContext.Provider.","Provide a mocked context value in tests/stories rather than relying on the throwing default.","Treat currentMonth === 'unknown' as a sentinel that the stub context is active."],"tags":["react","context","provider-missing","budget"],"backgroundTag":"context-used-outside-provider","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}