plandex-ai/plandex · error
error getting plan subtasks: %v %s
Error message
error getting plan subtasks: %v %s
What it means
This error is the panic-recovery path of the goroutine that calls db.GetPlanSubtasks(auth.OrgId, planId) in tell_load.go. If the goroutine panics (nil pointer, index out of range, nil DB handle), the deferred recover() logs the stack and sends 'error getting plan subtasks: <panic>\n<stack trace>' to errCh. Unlike the non-panic variant (index 742), it includes the full debug.Stack().
Source
Thrown at app/server/model/plan/tell_load.go:296
err := <-innerErrCh
if err != nil {
errCh <- err
return
}
}
if promptMsg != nil {
convo = append(convo, promptMsg)
}
errCh <- nil
}()
go func() {
defer func() {
if r := recover(); r != nil {
log.Printf("panic in getPlanSubtasks: %v\n%s", r, debug.Stack())
errCh <- fmt.Errorf("error getting plan subtasks: %v\n%s", r, debug.Stack())
runtime.Goexit() // don't allow outer function to continue and double-send to channel
}
}()
res, err := db.GetPlanSubtasks(auth.OrgId, planId)
if err != nil {
log.Printf("Error getting plan subtasks: %v\n", err)
errCh <- fmt.Errorf("error getting plan subtasks: %v", err)
return
}
subtasks = res
errCh <- nil
}()
for i := 0; i < 4; i++ {
err = <-errCh
if err != nil {
go notify.NotifyErr(notify.SeverityError, fmt.Errorf("error loading plan: %v", err))View on GitHub (pinned to e2d772072e)
Solutions
- Read the appended stack trace in the error/log to find the panicking line
- Fix the nil/race condition indicated by the stack
- Ensure auth.OrgId and planId are validated non-empty before load
- Check for concurrent writes to shared state from the parallel loader goroutines
Example fix
// before
go func() {
defer func() {
if r := recover(); r != nil {
errCh <- fmt.Errorf("error getting plan subtasks: %v\n%s", r, debug.Stack())
runtime.Goexit()
}
}()
res, err := db.GetPlanSubtasks(auth.OrgId, planId)
// after
if auth == nil || auth.OrgId == "" || planId == "" {
errCh <- fmt.Errorf("invalid auth or planId for subtasks")
return
}
go func() {
defer func() {
if r := recover(); r != nil {
errCh <- fmt.Errorf("error getting plan subtasks: %v\n%s", r, debug.Stack())
runtime.Goexit()
}
}()
res, err := db.GetPlanSubtasks(auth.OrgId, planId) Defensive patterns
Strategy: try-catch
Validate before calling
if auth == nil || auth.OrgId == "" || planId == "" {
return fmt.Errorf("missing orgId or planId for subtask load")
} Type guard
if db == nil {
return fmt.Errorf("db handle not initialized")
} Try / catch
defer func() {
if r := recover(); r != nil {
log.Printf("panic in getPlanSubtasks: %v\n%s", r, debug.Stack())
errCh <- fmt.Errorf("error getting plan subtasks: %v\n%s", r, debug.Stack())
runtime.Goexit()
}
}() Prevention
- Keep goroutines free of shared mutable state or guard it with mutexes
- Always recover in loader goroutines and send the error on the channel
- Initialize DB clients before spawning loaders
- Audit nil-dereference risks in result-mapping code
When it happens
Trigger: A runtime panic inside the getPlanSubtasks goroutine: nil auth or db handle, nil map access while building subtask results, or a panic propagated from the DB driver layer.
Common situations: Race on shared state during plan load, DB client initialized lazily and still nil, a driver bug triggered by malformed orgId/planId values.
Related errors
- error getting org user config: %v
- panic in UpdateContexts: %v\n%s
- panic in GetPlanConvo: %v\n%s
- panic in GetPlanDiffs: %v\n%s
- panic in gitRemoveIndexLockFileIfExists: %v %s
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/03b6c4d8246d5fce.
Report an issue: GitHub.