plandex-ai/plandex · error

error getting plan modelContext: %v

Error message

error getting plan modelContext: %v

What it means

This error is produced by the recover() handler in the getPlanContexts goroutine: any panic raised while assembling the plan's model context is converted into this error, sent to errCh, and the goroutine exits via runtime.Goexit so the outer function does not double-send. It means the context-loading goroutine crashed unexpectedly rather than returning a normal error — typically a nil map/slice or index-out-of-range while building modelContext.

Source

Thrown at app/server/model/plan/tell_load.go:145

					return nil
				})

				if err != nil {
					log.Printf("Error renaming plan: %v\n", err)
					errCh <- fmt.Errorf("error renaming plan: %v", err)
					return
				}
			}

			errCh <- nil
		}()

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

			if iteration > 0 || missingFileResponse != "" {
				modelContext = active.Contexts
			} else {
				res, err := db.GetPlanContexts(currentOrgId, planId, true, false)
				if err != nil {
					log.Printf("Error getting plan modelContext: %v\n", err)
					errCh <- fmt.Errorf("error getting plan modelContext: %v", err)
					return
				}

				log.Printf("[TellLoad] Tell plan - loadTellPlan - modelContext: %v\n", len(modelContext))
				// for _, part := range modelContext {
				// 	log.Printf("[TellLoad] Tell plan - loadTellPlan - part: %s - %s - %s - %d tokens\n", part.ContextType, part.Name, part.FilePath, part.NumTokens)
				// }

View on GitHub (pinned to e2d772072e)

Solutions

  1. Read the 'panic in getPlanContexts' log line with its stack trace to locate the panicking code
  2. Add nil/range checks around active.Contexts and the GetPlanContexts result before use
  3. Fix the underlying nil-pointer or index bug identified by the stack trace
  4. Re-run the request — this is a software defect, not a transient state
  5. Consider making the goroutine return errors instead of panicking so failures are typed and testable

Example fix

// before
if iteration > 0 || missingFileResponse != "" {
    modelContext = active.Contexts
}
// after
if iteration > 0 || missingFileResponse != "" {
    if active == nil || active.Contexts == nil {
        errCh <- fmt.Errorf("no active plan contexts available")
        return
    }
    modelContext = active.Contexts
}
Defensive patterns

Strategy: try-catch

Validate before calling

// guard before the goroutine body runs
if active == nil || active.Ctx == nil {
    return fmt.Errorf("no active plan available for context loading")
}
if iteration > 0 || missingFileResponse != "" {
    if active.Contexts == nil {
        return fmt.Errorf("active plan has no cached contexts")
    }
}

Type guard

func hasActiveContexts(ap *types.ActivePlan) bool {
    return ap != nil && ap.Contexts != nil && len(ap.Contexts) > 0
}

Try / catch

go func() {
    defer func() {
        if r := recover(); r != nil {
            log.Printf("panic in getPlanContexts: %v\n%s", r, debug.Stack())
            errCh <- fmt.Errorf("error getting plan modelContext: %v", r)
            runtime.Goexit()
        }
    }()
    ... // goroutine body
}()
// consumer side:
if err := <-errCh; err != nil {
    if strings.HasPrefix(err.Error(), "error getting plan modelContext") {
        // treat as unrecoverable software defect: fail request, alert with stack trace
    }
}

Prevention

When it happens

Trigger: A panic in the getPlanContexts goroutine — e.g. dereferencing a nil active plan/context, indexing into an empty modelContext slice, or a nil-pointer in code operating on active.Contexts or db results before the deferred recover fires.

Common situations: Concurrent map/slice access on ActivePlan while other goroutines mutate it; a code change introduced a nil dereference on a freshly created plan (iteration == 0 and no missingFileResponse); library upgrade changing GetPlanContexts return shape handled without nil checks.

Related errors


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