actualbudget/actual · error

Unsupported summary type

Error message

Unsupported summary type

What it means

summarySpreadsheet switches on summaryContent.type to compute the summary value (sum, avgPerTransact, avgPerMonth, avgPerYear, percentage). If the type matches none of the known cases, the default branch throws 'Unsupported summary type'. This guards against stale or invalid SummaryContent configs reaching the spreadsheet builder.

Source

Thrown at packages/desktop-client/src/components/reports/spreadsheets/summary-spreadsheet.ts:182

          ...calculatePerYear(data.data, startDay, endDay),
        });
        break;
      }

      case 'percentage':
        setData({
          ...dateRanges,
          ...(await calculatePercentage(
            data.data,
            summaryContent,
            startDay,
            endDay,
          )),
        });
        break;

      default:
        throw new Error(`Unsupported summary type`);
    }
  };
}

function calculatePerMonth(
  data: Array<{
    date: string;
    amount: number;
    count: number;
  }>,
  months: Date[],
) {
  if (!data.length || !months.length) {
    return { total: 0, dividend: 0, divisor: 0 };
  }

  const monthlyData = data.reduce(
    (acc, day) => {

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Inspect summaryContent.type at the call site and use one of the supported values: sum, avgPerTransact, avgPerMonth, avgPerYear, percentage
  2. If the config is persisted, migrate or re-create the summary widget so it stores a valid type
  3. Narrow the input with the SummaryContent type union and let TypeScript catch invalid types at compile time
  4. Wrap in try/catch and render a fallback message for unknown summary types

Example fix

// before
summarySpreadsheet(start, end, conditions, op, { type: 'average' } as SummaryContent, locale);
// after
summarySpreadsheet(start, end, conditions, op, { type: 'avgPerMonth' } satisfies SummaryContent, locale);
Defensive patterns

Strategy: type-guard

Validate before calling

const SUPPORTED = ['sum','avgPerTransact','avgPerMonth','avgPerYear','percentage'] as const;
if (!SUPPORTED.includes(summaryContent.type)) throw new Error(`Unsupported summary type: ${summaryContent.type}`);

Type guard

function isSummaryType(t: unknown): t is 'sum' | 'avgPerTransact' | 'avgPerMonth' | 'avgPerYear' | 'percentage' {
  return typeof t === 'string' && ['sum','avgPerTransact','avgPerMonth','avgPerYear','percentage'].includes(t);
}

Try / catch

try {
  await builder(spreadsheet, setData);
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Unsupported summary type')) {
    setData({ total: 0, divisor: 0, dividend: 0, fromRange: '', toRange: '' });
  } else throw e;
}

Prevention

When it happens

Trigger: Passing a summaryContent object whose type is not one of 'sum' | 'avgPerTransact' | 'avgPerMonth' | 'avgPerYear' | 'percentage' — e.g. a typo like 'avgpermonth', an old serialized config from a previous schema, or a new type added in the UI before the spreadsheet supports it.

Common situations: Persisted dashboard/report JSON created by a newer or older version of the app being loaded by a version without that summary type; plugin or API code constructing SummaryContent by hand with an invalid type; a rename of the type union not migrated in stored configs.

Related errors


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