Bug Description
The app crashes with TypeError: Cannot read properties of undefined (reading 'month') when a budget, section, or category exists with an empty capacities array.
Error location: LabeledBar/index.tsx:40 — barData.getActiveCapacity(date) returns undefined when capacities is empty.
Root Cause
Two issues combine:
1. Subclass constructors wipe the default capacity
BudgetFamily constructor correctly adds a fallback capacity when capacities is empty:
// BudgetFamily constructor
assign(this, init);
this.fromJSON();
if (!this.capacities.length) this.capacities = [new Capacity()]; // ✅ Adds default
But all three subclasses (Budget, Section, Category) re-assign from init after calling super():
// Budget/Section/Category constructor
super(init); // ✅ BudgetFamily adds default capacity
assign(this, init); // ❌ Overwrites capacities with the original [] from init
this.fromJSON(); // Maps over empty array → still empty
The second assign(this, init) overwrites the default capacity added by the parent constructor.
2. Server creates budgets with empty capacities
createBudget in budgets.ts uses data.capacities || [] — creating budgets with no capacities in the database.
Reproduction
- The DB currently has two budgets with
capacities: []:
86a6f730-5a72-4ec6-9415-6446a18d87d8 (New Budget)
540b7170-5c5b-42b0-941a-f1d814db116b (New Budget)
- Loading the app (budgets page) crashes immediately
Proposed Fix
Client: In getActiveCapacity, return a default new Capacity() when capacities is empty (defensive), and fix the subclass constructors to not re-assign capacities from init (root cause).
Server: createBudget should provide a default capacity when none is specified.
Data cleanup: Update the two existing budgets with empty capacities:
UPDATE budgets SET capacities = '[{"month": 0, "capacity_id": "default"}]' WHERE capacities = '[]';
Impact
- Severity: High — crashes the entire app (error boundary catches but no recovery)
- Scope: Affects any user who creates a budget without immediately configuring a capacity
- Persistence: IndexedDB caches the broken data, so clearing browser state also fails until IDB is manually wiped
Bug Description
The app crashes with
TypeError: Cannot read properties of undefined (reading 'month')when a budget, section, or category exists with an emptycapacitiesarray.Error location:
LabeledBar/index.tsx:40—barData.getActiveCapacity(date)returnsundefinedwhencapacitiesis empty.Root Cause
Two issues combine:
1. Subclass constructors wipe the default capacity
BudgetFamilyconstructor correctly adds a fallback capacity whencapacitiesis empty:But all three subclasses (
Budget,Section,Category) re-assign frominitafter callingsuper():The second
assign(this, init)overwrites the default capacity added by the parent constructor.2. Server creates budgets with empty capacities
createBudgetinbudgets.tsusesdata.capacities || []— creating budgets with no capacities in the database.Reproduction
capacities: []:86a6f730-5a72-4ec6-9415-6446a18d87d8(New Budget)540b7170-5c5b-42b0-941a-f1d814db116b(New Budget)Proposed Fix
Client: In
getActiveCapacity, return a defaultnew Capacity()whencapacitiesis empty (defensive), and fix the subclass constructors to not re-assigncapacitiesfrominit(root cause).Server:
createBudgetshould provide a default capacity when none is specified.Data cleanup: Update the two existing budgets with empty capacities:
Impact