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

  1. Read the logged stack trace (also embedded in the error) to locate the panicking line in RejectPlanFile
  2. Fix the nil-dereference/race at the identified location; guard nil result fields before use
  3. Re-run RejectAllResults after the fix; only the panicking resultId failed, others were processed
  4. 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

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


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/4f7337ab4c14907e. Report an issue: GitHub.