actualbudget/actual · error

Unitialised context method called: onToggleSummaryCollapse

Error message

Unitialised context method called: onToggleSummaryCollapse

What it means

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.

Source

Thrown at packages/desktop-client/src/components/budget/tracking/TrackingBudgetContext.tsx:19

import React, { createContext, useContext } from 'react';
import type { ReactNode } from 'react';

import * as monthUtils from '@actual-app/core/shared/months';

type TrackingBudgetContextDefinition = {
  summaryCollapsed: boolean;
  onBudgetAction: (month: string, action: string, arg?: unknown) => void;
  onToggleSummaryCollapse: () => void;
  currentMonth: string;
};

const TrackingBudgetContext = createContext<TrackingBudgetContextDefinition>({
  summaryCollapsed: false,
  onBudgetAction: () => {
    throw new Error('Unitialised context method called: onBudgetAction');
  },
  onToggleSummaryCollapse: () => {
    throw new Error(
      'Unitialised context method called: onToggleSummaryCollapse',
    );
  },
  currentMonth: 'unknown',
});

type TrackingBudgetProviderProps = Omit<
  TrackingBudgetContextDefinition,
  'currentMonth'
> & {
  children: ReactNode;
};
export function TrackingBudgetProvider({
  summaryCollapsed,
  onBudgetAction,
  onToggleSummaryCollapse,
  children,
}: TrackingBudgetProviderProps) {

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Mount TrackingBudgetContext.Provider above the consumer with a real onToggleSummaryCollapse callback.
  2. Check that the provider's value object actually includes onToggleSummaryCollapse (not just onBudgetAction).
  3. Wrap isolated renders (Storybook, tests) with the provider or a test harness that supplies both methods.

Example fix

// before
render(<BudgetSummary />); // uses context default -> throws on toggle

// after
render(
  <TrackingBudgetContext.Provider value={{ summaryCollapsed: false, onBudgetAction: vi.fn(), onToggleSummaryCollapse: vi.fn(), currentMonth: '2026-08' }}>
    <BudgetSummary />
  </TrackingBudgetContext.Provider>
);
Defensive patterns

Strategy: try-catch

Validate before calling

const ctx = useContext(TrackingBudgetContext);
if (typeof ctx.onToggleSummaryCollapse !== 'function' || isDefaultStub(ctx.onToggleSummaryCollapse)) {
  throw new Error('TrackingBudgetContext provider missing onToggleSummaryCollapse');
}

Type guard

function canToggleSummary(ctx: TrackingBudgetContextDefinition): boolean {
  return typeof ctx.onToggleSummaryCollapse === 'function';
}

Try / catch

try {
  onToggleSummaryCollapse();
} catch (err) {
  if (err instanceof Error && err.message.includes('Unitialised context method called: onToggleSummaryCollapse')) {
    logger.warn('Summary collapse unavailable: TrackingBudgetContext not provided');
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Clicking the collapse/expand summary toggle in a component that consumed TrackingBudgetContext without a TrackingBudgetContext.Provider ancestor supplying onToggleSummaryCollapse.

Common situations: 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.

Related errors


AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29). Data as JSON: /api/errors/ddf46846450350b4. Report an issue: GitHub.