fix(practice): add defensive checks in recordSlotResult

Add robust error handling to recordSlotResult to prevent cryptic
"Cannot read properties of undefined" errors:

- Check that plan.parts exists and is a valid array before indexing
- Validate currentPartIndex is within valid bounds
- Ensure the database update returned a result

These checks provide clearer error messages when data is corrupted
or in an invalid state, helping diagnose production issues.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock 2025-12-13 06:48:39 -06:00
parent 9f07bd6df6
commit a33e3e6d2b
1 changed files with 20 additions and 0 deletions

View File

@ -503,6 +503,19 @@ export async function recordSlotResult(
const plan = await getSessionPlan(planId)
if (!plan) throw new Error(`Plan not found: ${planId}`)
// Defensive check: ensure parts array exists and is valid
if (!plan.parts || !Array.isArray(plan.parts)) {
throw new Error(
`Plan ${planId} has invalid parts: ${typeof plan.parts} (status: ${plan.status}, partIndex: ${plan.currentPartIndex})`
)
}
if (plan.currentPartIndex < 0 || plan.currentPartIndex >= plan.parts.length) {
throw new Error(
`Plan ${planId} has invalid currentPartIndex: ${plan.currentPartIndex} (parts.length: ${plan.parts.length})`
)
}
const currentPart = plan.parts[plan.currentPartIndex]
if (!currentPart) throw new Error(`Invalid part index: ${plan.currentPartIndex}`)
@ -545,6 +558,13 @@ export async function recordSlotResult(
.where(eq(schema.sessionPlans.id, planId))
.returning()
// Defensive check: ensure update succeeded
if (!updated) {
throw new Error(
`Failed to update plan ${planId}: no rows returned (may have been deleted during update)`
)
}
// Update global skill mastery with response time data
// This builds the per-kid stats for identifying strengths/weaknesses
if (result.skillsExercised && result.skillsExercised.length > 0) {