fix(dashboard): defensive guards prevent 'is not iterable' on partial backend responses (closes #304)#311
Conversation
… backend responses (closes #304) The 'Failed to load dashboard: e is not iterable' error was triggered when api.getRecommendations() resolved to a non-array value. The apiRequest() catch block returns `null as T` when response.json() fails on a 2xx response with an empty or non-JSON body; a non-array envelope shape from the backend produces the same symptom. Both land in groupRecsByCell() which iterates via `for...of`, throwing "null/X is not iterable" and replacing the dashboard with an error banner. Two layered guards added to dashboard.ts: - Array.isArray() check in loadDashboard() coerces any non-array recsResult value to [] before it reaches groupRecsByCell(). - try/catch soft-fail in renderDashboardSummary() around the groupRecsByCell/pageLevelRange computation so the savings card degrades to $0 rather than blanking the entire dashboard if the guard above is ever bypassed. Regression tests added for: (a) getRecommendations() returning null (b) getRecommendations() returning a non-array object ({recommendations:[]}) (c) summaryData missing by_service field entirely
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR adds defensive error handling to dashboard data loading to prevent crashes when API endpoints return unexpected data shapes (null, non-array objects, missing fields). It guards against iteration errors in recommendations processing and wraps savings calculations in a try/catch fallback to zero. ChangesDashboard Defensive Guards
Estimated code review effort🎯 2 (Simple) | ⏱️ ~15 minutes Possibly related issues
Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
Summary
getRecommendations()can resolve tonull(whenapiRequest's JSON-parse catch fires on a 2xx with empty/non-JSON body) or an unexpected object shape — both reachgroupRecsByCell()which usesfor...of, throwing"X is not iterable"and replacing the entire dashboard with an error banner.Array.isArray()guard inloadDashboard()to coerce any non-array fulfilled value to[]before it reachesgroupRecsByCell().renderDashboardSummary()around the savings-range computation so the Potential Monthly Savings card degrades to$0rather than blanking the dashboard if the guard is ever bypassed.Fault site (PR #295 — commit e4a52f9)
Regression tests added
#304: getRecommendations returning null does not throw "is not iterable"#304: getRecommendations returning a non-array object does not throw "is not iterable"#304: summaryData missing by_service field does not throwAll 24 dashboard tests pass.
Test plan
cd frontend && npm test -- --testPathPattern=dashboard— all 24 tests pass#304tests are green/recommendations— other cards still render, savings card shows$0Closes #304
Summary by CodeRabbit
Bug Fixes