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
- Examine the wrapped child error for the exact file or directory
- Repair permissions or delete/fix the corrupt context file
- Restore the plan's contexts directory from backup
- Avoid running concurrent deletions against the plans data dir
- 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
- Restore contexts dir from backup rather than deleting files ad hoc
- Enforce consistent service-user ownership across data dirs
- Use atomic writes for all stored JSON to prevent truncation
- Quarantine corrupt files and alert instead of letting load fail entirely
- Avoid manual edits to stored context JSON
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
- error getting plan file results: %v
- error getting latest plan build description: %v
- error unmarshalling settings-v2.json: %v
- error reading settings-v2.json: %v
- failed to seek in temporary file: %w
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/f22ab8e36a31ef82.
Report an issue: GitHub.