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
- Read the stack trace after 'panic getting plan settings' to find the nil deref source
- Inspect the plan's settings row in the DB for missing/invalid fields and repair or reset them
- Check DB connectivity and that the plans/settings schema is fully migrated
- 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
- Nil-check plan fields inside GetPlanSettings before dereferencing
- Validate settings JSON shape on read to avoid nil maps/pointers
- Keep schema migrations in sync with the settings struct
- Watch 'panic in getPlanSettings' logs for recurring stack traces
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
- panic in SyncPlanTokens: %v %s
- error getting org user config: %v
- error getting current plan state: %v
- error getting plan convo: %v
- error starting fast apply: %v
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/5d541b589474a433.
Report an issue: GitHub.