plandex-ai/plandex · error
panic in RejectAllResults: %v\n%s
Error message
panic in RejectAllResults: %v\n%s
What it means
RejectAllResults spawns a goroutine per result file; each goroutine has a recover() defer that converts a panic into this error message (including a stack dump), logs it, and sends it on errCh before calling runtime.Goexit(). This message means RejectPlanFile (or nearby code) panicked while rejecting a result.
Source
Thrown at app/server/db/result_helpers.go:813
if err != nil {
if os.IsNotExist(err) {
return nil
}
return fmt.Errorf("error reading results dir: %v", err)
}
errCh := make(chan error, len(files))
now := time.Now()
for _, file := range files {
resultId := strings.TrimSuffix(file.Name(), ".json")
go func(resultId string) {
defer func() {
if r := recover(); r != nil {
log.Printf("panic in RejectAllResults: %v\n%s", r, debug.Stack())
errCh <- fmt.Errorf("panic in RejectAllResults: %v\n%s", r, debug.Stack())
runtime.Goexit() // don't allow outer function to continue and double-send to channel
}
}()
err := RejectPlanFile(orgId, planId, resultId, now)
if err != nil {
errCh <- fmt.Errorf("error rejecting result: %v", err)
return
}
errCh <- nil
}(resultId)
}
for i := 0; i < len(files); i++ {
err := <-errCh
if err != nil {
return fmt.Errorf("error rejecting plan: %v", err)View on GitHub (pinned to e2d772072e)
Solutions
- Read the logged stack trace (also embedded in the error) to locate the panicking line in RejectPlanFile
- Fix the nil-dereference/race at the identified location; guard nil result fields before use
- Re-run RejectAllResults after the fix; only the panicking resultId failed, others were processed
- Add a unit test reproducing the corrupt/edge-case result file
Example fix
// before: panic on nil inside RejectPlanFile
path := result.ToApi().Path
// after: guard nil
toApi := result.ToApi()
if toApi == nil || toApi.Path == "" {
return fmt.Errorf("result %s has no path", resultId)
}
path := toApi.Path Defensive patterns
Strategy: try-catch
Type guard
func safeReject(orgId, planId, resultId string, now time.Time) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic in RejectPlanFile(%s): %v\n%s", resultId, r, debug.Stack())
}
}()
return RejectPlanFile(orgId, planId, resultId, now)
} Try / catch
go func(resultId string) {
defer func() {
if r := recover(); r != nil {
log.Printf("panic in RejectAllResults: %v\n%s", r, debug.Stack())
errCh <- fmt.Errorf("panic in RejectAllResults: %v\n%s", r, debug.Stack())
runtime.Goexit()
}
}()
_ = RejectPlanFile(orgId, planId, resultId, now)
}(resultId) Prevention
- Guard nil fields on PlanFileResult before dereferencing (ToApi/Path)
- Add -race test runs for code that mutates plan state across goroutines
- Unit-test RejectPlanFile with corrupt/minimal JSON fixtures
- Keep recover()+Goexit pattern consistent in every spawned goroutine
When it happens
Trigger: A nil pointer dereference or index-out-of-range inside RejectPlanFile/org/plan/result handling; unexpected nil result data; any runtime panic raised inside the spawned goroutine while rejecting a specific resultId.
Common situations: Corrupt or hand-edited result JSON causing unexpected nil fields dereferenced downstream; concurrent mutation of shared plan state across goroutines; regressions in RejectPlanFile after refactors surfacing only under real data.
Related errors
- panic in UpdateContexts: %v\n%s
- panic in GetPlanConvo: %v\n%s
- panic in gitRemoveIndexLockFileIfExists: %v %s
- panic in DeleteDraftPlans: %v %s
- panic in GetFullCurrentPlanStateParams: %v\n%s
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/4f7337ab4c14907e.
Report an issue: GitHub.