plandex-ai/plandex · error

error getting default plan config: %v

Error message

error getting default plan config: %v

What it means

Inside CreatePlan's WithTx callback, an error from GetDefaultPlanConfig(userId) is re-wrapped with this identical message ('error getting default plan config'). It means the new plan's starting config could not be loaded from the user's row — usually because the userId doesn't exist in users (sql.ErrNoRows) — and causes the whole 'create plan' transaction to roll back.

Source

Thrown at app/server/db/plan_helpers.go:30

	"strconv"
	"time"

	shared "plandex-shared"

	"github.com/google/uuid"
	"github.com/jmoiron/sqlx"
	"github.com/lib/pq"
	"github.com/sashabaranov/go-openai"
)

func CreatePlan(ctx context.Context, orgId, projectId, userId, name string) (*Plan, error) {
	var plan *Plan
	err := WithTx(ctx, "create plan", func(tx *sqlx.Tx) error {

		planConfig, err := GetDefaultPlanConfig(userId)

		if err != nil {
			return fmt.Errorf("error getting default plan config: %v", err)
		}

		query := `INSERT INTO plans (org_id, owner_id, project_id, name, plan_config) 
	VALUES ($1, $2, $3, $4, $5)
	RETURNING id, created_at, updated_at`

		plan = &Plan{
			OrgId:      orgId,
			OwnerId:    userId,
			ProjectId:  projectId,
			Name:       name,
			PlanConfig: planConfig,
		}

		err = tx.QueryRow(
			query,
			orgId,
			userId,

View on GitHub (pinned to e2d772072e)

Solutions

  1. Unwrap the nested cause: 'no rows in result set' means the userId is invalid — verify the user exists/authenticates before CreatePlan
  2. Apply migrations / seed data if users.default_plan_config or the users row is missing
  3. For scan errors, inspect and repair the user's default_plan_config JSON
  4. On transient connection errors, retry CreatePlan after DB health is restored (the tx rolled back cleanly)

Example fix

// before
planConfig, err := GetDefaultPlanConfig(userId)
if err != nil {
    return fmt.Errorf("error getting default plan config: %v", err)
}
// after: fail fast with a distinct not-found path
planConfig, err := GetDefaultPlanConfig(userId)
if err != nil {
    if strings.Contains(err.Error(), "no rows in result set") {
        return fmt.Errorf("user %s not found: %w", userId, err)
    }
    return fmt.Errorf("error getting default plan config: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

// verify user exists before CreatePlan
var exists bool
if err := Conn.Get(&exists, "SELECT EXISTS(SELECT 1 FROM users WHERE id=$1)", userId); err != nil || !exists {
    return nil, fmt.Errorf("cannot create plan: user %s not found", userId)
}

Try / catch

plan, err := CreatePlan(ctx, orgId, projectId, userId, name)
if err != nil {
    if strings.Contains(err.Error(), "no rows in result set") {
        return nil, fmt.Errorf("user has no default plan config / not found")
    }
    log.Printf("CreatePlan: %v", err)
    return nil, err
}

Prevention

When it happens

Trigger: CreatePlan runs with a userId that has no users row, a DB connection failure, or a default_plan_config value that can't scan into shared.PlanConfig; the WithTx('create plan') transaction then rolls back and no plan is created.

Common situations: Plan creation triggered by a stale or forged session whose user was deleted; environment where user seed data is missing; corrupted default_plan_config JSON; transient Postgres outage during plan creation.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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