plandex-ai/plandex · error

Error getting plan config

Error message

Error getting plan config

What it means

GetPlanConfigHandler returns HTTP 500 when db.GetPlanConfig(planId) errors after plan authorization succeeded. The handler deliberately returns a fixed message, hiding the underlying cause, so server logs are required to diagnose it.

Source

Thrown at app/server/handlers/plan_config.go:37

	auth := Authenticate(w, r, true)
	if auth == nil {
		return
	}

	vars := mux.Vars(r)
	planId := vars["planId"]

	log.Println("planId: ", planId)

	plan := authorizePlan(w, planId, auth)
	if plan == nil {
		return
	}

	config, err := db.GetPlanConfig(planId)
	if err != nil {
		log.Println("Error getting plan config: ", err)
		http.Error(w, "Error getting plan config", http.StatusInternalServerError)
		return
	}

	res := shared.GetPlanConfigResponse{
		Config: config,
	}

	bytes, err := json.Marshal(res)
	if err != nil {
		log.Println("Error marshalling response: ", err)
		http.Error(w, "Error marshalling response", http.StatusInternalServerError)
		return
	}

	w.Write(bytes)
	log.Println("GetPlanConfigHandler processed successfully")
}

View on GitHub (pinned to e2d772072e)

Solutions

  1. Check server logs for "Error getting plan config: <err>" to see the real cause
  2. Run migrations to confirm the plan_configs table exists and matches the model
  3. Fix or regenerate corrupt config rows (invalid JSON in the column)
  4. Verify DB connectivity and retry after transient failures

Example fix

// before
http.Error(w, "Error getting plan config", http.StatusInternalServerError)
// after
if errors.Is(err, sql.ErrNoRows) {
    http.Error(w, "Error getting plan config", http.StatusNotFound)
    return
}
http.Error(w, "Error getting plan config", http.StatusInternalServerError)
Defensive patterns

Strategy: retry

Validate before calling

// client: only call for a plan you can access
const plan = await getPlan(planId);
if (!plan) return; // 404/403 handled by authorizePlan before this error

Try / catch

try {
  const cfg = await getPlanConfig(planId);
} catch (e) {
  if (e.status === 500) { await backoffRetry(e, { attempts: 3 }); }
  else throw e;
}

Prevention

When it happens

Trigger: GET plan config where the plan_configs row for planId is missing/unreadable, the DB is unreachable, or the config data fails to scan (e.g. invalid JSON stored in the config column).

Common situations: Config row deleted manually, corrupt JSON in the stored config after a manual DB edit, schema drift after version upgrade, transient database outages.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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