plandex-ai/plandex · error

error deleting pending results: %v

Error message

error deleting pending results: %v

What it means

DeletePendingResultsForPaths collects one error per goroutine from errCh and wraps the first failure as 'error deleting pending results: %v'. Any per-file failure (read, unmarshal, delete, or panic) surfaces here as the aggregate error returned to the caller.

Source

Thrown at app/server/db/result_helpers.go:899

			if result.ToApi().IsPending() && paths[result.Path] {
				log.Printf("Deleting pending result: %s", resultId)

				err = os.Remove(filepath.Join(resultsDir, resultId+".json"))

				if err != nil {
					errCh <- fmt.Errorf("error deleting result file: %v", err)
					return
				}
			}

			errCh <- nil
		}(resultId)
	}

	for i := 0; i < len(files); i++ {
		err := <-errCh
		if err != nil {
			return fmt.Errorf("error deleting pending results: %v", err)
		}
	}

	return nil
}

func RejectPlanFiles(orgId, planId string, files []string, now time.Time) error {
	errCh := make(chan error, len(files))

	for _, file := range files {
		go func(file string) {
			defer func() {
				if r := recover(); r != nil {
					log.Printf("panic in RejectPlanFiles: %v\n%s", r, debug.Stack())
					errCh <- fmt.Errorf("panic in RejectPlanFiles: %v\n%s", r, debug.Stack())
					runtime.Goexit() // don't allow outer function to continue and double-send to channel
				}
			}()

View on GitHub (pinned to e2d772072e)

Solutions

  1. Inspect the wrapped %v to identify the per-file root cause (read/unmarshal/delete/panic)
  2. Clean or repair the offending result file or fix directory permissions
  3. Harden per-file handling so transient issues are logged and skipped rather than failing the sweep
  4. Restrict mutation of the results directory to this code path to avoid races

Example fix

// before
err := <-errCh
if err != nil {
    return fmt.Errorf("error deleting pending results: %v", err)
}
// after
err := <-errCh
if err != nil {
    log.Printf("pending-result cleanup error (continuing): %v", err)
    lastErr = err
}
// return lastErr at end if policy requires
Defensive patterns

Strategy: try-catch

Validate before calling

entries, err := os.ReadDir(getPlanResultsDir(orgId, planId))
if err != nil && !os.IsNotExist(err) {
    return fmt.Errorf("cannot read results dir: %v", err)
}
for _, e := range entries {
    b, _ := os.ReadFile(filepath.Join(resultsDir, e.Name()))
    if !json.Valid(b) { log.Printf("corrupt result file: %s", e.Name()) }
}

Try / catch

if err := DeletePendingResultsForPaths(orgId, planId, paths); err != nil {
    log.Printf("deleting pending results failed: %v", err)
    // unwrap: errors like 'error unmarshalling result file' point to corrupt data
}

Prevention

When it happens

Trigger: Any goroutine in the sweep fails: result file unreadable, unparseable JSON, os.Remove failure, or a recovered panic in a worker goroutine.

Common situations: Corrupt or foreign files in the results dir; permission problems on the results directory; race with another process deleting files concurrently.

Related errors


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