plandex-ai/plandex · error

error getting contexts: %v

Error message

error getting contexts: %v

What it means

If GetPlanContexts returns an error inside GetFullCurrentPlanStateParams, it is re-wrapped as 'error getting contexts' and aborts the whole plan-state load (the collector loop returns on the first non-nil error).

Source

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

		if err != nil {
			errCh <- fmt.Errorf("error getting latest plan build description: %v", err)
			return
		}
		convoMessageDescriptions = res
		errCh <- nil
	}()

	go func() {
		defer func() {
			if r := recover(); r != nil {
				log.Printf("panic in GetFullCurrentPlanStateParams: %v\n%s", r, debug.Stack())
				errCh <- fmt.Errorf("panic in GetFullCurrentPlanStateParams: %v\n%s", r, debug.Stack())
				runtime.Goexit() // don't allow outer function to continue and double-send to channel
			}
		}()
		res, err := GetPlanContexts(orgId, planId, true, false)
		if err != nil {
			errCh <- fmt.Errorf("error getting contexts: %v", err)
			return
		}

		contexts = res

		errCh <- nil
	}()

	for i := 0; i < 3; i++ {
		err := <-errCh
		if err != nil {
			return CurrentPlanStateParams{}, err
		}
	}

	return CurrentPlanStateParams{
		OrgId:                    orgId,
		PlanId:                   planId,

View on GitHub (pinned to e2d772072e)

Solutions

  1. Examine the wrapped child error for the exact file or directory
  2. Repair permissions or delete/fix the corrupt context file
  3. Restore the plan's contexts directory from backup
  4. Avoid running concurrent deletions against the plans data dir
  5. Consider making single-file corruption non-fatal by skipping bad contexts

Example fix

// before
if err != nil {
	return CurrentPlanStateParams{}, err
}
// after
if err != nil {
	log.Printf("contexts load failed for %s/%s: %v", orgId, planId, err)
	return CurrentPlanStateParams{OrgId: orgId, PlanId: planId}, nil
}
Defensive patterns

Strategy: fallback

Validate before calling

func contextsReadable(orgId, planId string) error {
	dir := getPlanContextsDir(orgId, planId)
	files, err := os.ReadDir(dir)
	if err != nil {
		if os.IsNotExist(err) {
			return nil
		}
		return err
	}
	for _, f := range files {
		b, err := os.ReadFile(filepath.Join(dir, f.Name()))
		if err != nil || !json.Valid(b) {
			return fmt.Errorf("bad context file %s", f.Name())
		}
	}
	return nil
}

Type guard

func isPermissionErr(err error) bool {
	var pe *os.PathError
	return errors.As(err, &pe) && errors.Is(pe.Err, syscall.EACCES)
}

Try / catch

params, err := db.GetFullCurrentPlanStateParams(orgId, planId)
if err != nil && strings.Contains(err.Error(), "error getting contexts") {
	log.Printf("contexts unavailable, continuing without them: %v", err)
	params.Contexts = nil
}

Prevention

When it happens

Trigger: GetPlanContexts fails: contexts directory unreadable (non-ENOENT), a context file unreadable or fails JSON unmarshal, or one of its internal goroutines panics/errors.

Common situations: Context files truncated by a crash; permissions changed on the contexts dir; invalid JSON from a manual edit or partial write; storage corruption after a disk issue.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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