actualbudget/actual · error

Unitialised context method called: onToggleSummaryCollapse

Error message

Unitialised context method called: onToggleSummaryCollapse

What it means

The sibling stub in EnvelopeBudgetContext: onToggleSummaryCollapse throws when the default (provider-less) context value is used. The collapse toggle only works when the real provider has wired it to local state in the envelope budget component.

Source

Thrown at packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetContext.tsx:19

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

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

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

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

type EnvelopeBudgetProviderProps = Omit<
  EnvelopeBudgetContextDefinition,
  'currentMonth'
> & {
  children: ReactNode;
};
export function EnvelopeBudgetProvider({
  summaryCollapsed,
  onBudgetAction,
  onToggleSummaryCollapse,
  children,
}: EnvelopeBudgetProviderProps) {

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Render the toggle under EnvelopeBudgetContext.Provider so the real state-backed handler is used.
  2. Mock the context in tests with a no-op onToggleSummaryCollapse and assert it gets called instead of relying on the throwing default.
  3. Check currentMonth !== 'unknown' before wiring UI to the context, surfacing a clear 'not inside provider' warning instead of crashing on click.

Example fix

// before
const { onToggleSummaryCollapse } = useContext(EnvelopeBudgetContext);

// after (guard against stub context)
const ctx = useContext(EnvelopeBudgetContext);
if (ctx.currentMonth === 'unknown') {
  console.warn('EnvelopeBudgetContext provider missing');
  return null;
}
Defensive patterns

Strategy: try-catch

Validate before calling

const ctx = useContext(EnvelopeBudgetContext);
if (ctx.currentMonth === 'unknown') {
  console.warn('onToggleSummaryCollapse called without EnvelopeBudgetContext.Provider');
  return;
}

Type guard

function isInitializedEnvelopeContext(ctx: EnvelopeBudgetContextDefinition): ctx is EnvelopeBudgetContextDefinition & { currentMonth: string } {
  return ctx.currentMonth !== 'unknown';
}

Try / catch

try {
  onToggleSummaryCollapse();
} catch (e) {
  if (String(e.message).includes('Unitialised context method')) {
    setSummaryCollapsed(c => !c); // local fallback
  } else throw e;
}

Prevention

When it happens

Trigger: Clicking a summary collapse toggle (or calling onToggleSummaryCollapse from a custom component) outside the EnvelopeBudgetContext.Provider tree, including isolated test renders.

Common situations: Standalone renders of the budget summary/notes components; tests without the provider wrapper; refactors relocating the toggle component above the provider.

Related errors


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