plandex-ai/plandex · error

panic getting plan settings: %v %s

Error message

panic getting plan settings: %v
%s

What it means

This error is produced when the goroutine that fetches plan settings (db.GetPlanSettings) panics; the deferred recover converts the panic into an error sent on errCh. debug.Stack() is appended so the developer sees the panic site. runtime.Goexit stops the goroutine to avoid double-sending on the channel.

Source

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

	db.ExecRepoOperation(db.ExecRepoOperationParams{
		OrgId:    auth.OrgId,
		UserId:   auth.User.Id,
		PlanId:   planId,
		Branch:   branch,
		Scope:    lockScope,
		Ctx:      active.Ctx,
		CancelFn: active.CancelFn,
		Reason:   "load tell plan",
	}, func(repo *db.GitRepo) error {
		errCh := make(chan error, 4)

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

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

			orgUserConfigRes, err := db.GetOrgUserConfig(auth.User.Id, auth.OrgId)
			if err != nil {
				log.Printf("Error getting org user config: %v\n", err)
				errCh <- fmt.Errorf("error getting org user config: %v", err)
				return
			}

View on GitHub (pinned to e2d772072e)

Solutions

  1. Read the stack trace after 'panic getting plan settings' to find the nil deref source
  2. Inspect the plan's settings row in the DB for missing/invalid fields and repair or reset them
  3. Check DB connectivity and that the plans/settings schema is fully migrated
  4. Patch GetPlanSettings to nil-check before dereferencing

Example fix

// before
res, err := db.GetPlanSettings(plan) // panics on nil plan.ModelPack
// after
if plan == nil || plan.Id == "" {
    errCh <- fmt.Errorf("cannot load settings: plan is nil")
    return
}
res, err := db.GetPlanSettings(plan)
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure plan and its required fields exist before loading settings
if plan == nil || plan.Id == "" {
    return errors.New("plan is nil or has no id; cannot load settings")
}

Try / catch

select {
case err := <-errCh:
    if strings.HasPrefix(err.Error(), "panic getting plan settings:") {
        // log stack trace, reset plan settings row to defaults, retry once
    }
case res := <-resCh:
    settings = res
}

Prevention

When it happens

Trigger: db.GetPlanSettings panics — typically a nil pointer inside settings loading (nil plan fields, nil DB handle, nil embedded config dereference) or an unexpected data shape from the database.

Common situations: Corrupted or partially-migrated plan settings row missing required JSON fields; DB connection closed mid-query causing nil deref downstream; concurrent plan mutation while settings load.

Related errors


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