plandex-ai/plandex · error

error initializing plan dir: %v

Error message

error initializing plan dir: %v

What it means

This error wraps a failure from InitPlan(orgId, plan.Id) in CreatePlan (app/server/db/plan_helpers.go:82). InitPlan creates the plan's working directory structure on disk after the git 'main' branch exists. A failure here means the DB transaction rolled back even though the plan row, lockable id, and branch creation succeeded within the transaction, leaving possible orphaned on-disk artifacts.

Source

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

		if err != nil {
			return fmt.Errorf("error inserting lockable plan id: %v", err)
		}

		// the one place where we do this to skip the locking queue
		// ok to cheat this once since we're creating a new plan
		repo := getGitRepo(orgId, plan.Id)
		_, err = CreateBranch(repo, plan, nil, "main", tx)

		if err != nil {
			return fmt.Errorf("error creating main branch: %v", err)
		}

		log.Println("Created branch main")

		err = InitPlan(orgId, plan.Id)

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

		log.Println("Initialized plan dir")

		return nil
	})

	if err != nil {
		return nil, err
	}

	return plan, nil
}

func ListOwnedPlans(projectIds []string, userId string, archived bool) ([]*Plan, error) {
	qs := "SELECT * FROM plans WHERE project_id = ANY($1) AND owner_id = $2"
	qargs := []interface{}{pq.Array(projectIds), userId}

View on GitHub (pinned to e2d772072e)

Solutions

  1. Inspect the wrapped %v message and server logs for the underlying os-level error (permission denied, no space left on device)
  2. Fix filesystem permissions and free disk space on the plan storage volume
  3. Remove the orphaned plan directory for the failed plan id, then retry CreatePlan
  4. Add a pre-flight check in CreatePlan that the storage root is writable before starting the transaction

Example fix

// before
err = InitPlan(orgId, plan.Id)
if err != nil {
    return fmt.Errorf("error initializing plan dir: %v", err)
}
// after (fail fast with wrapped cause and clean stale dir)
if err := InitPlan(orgId, plan.Id); err != nil {
    os.RemoveAll(getPlanDir(orgId, plan.Id))
    return fmt.Errorf("error initializing plan dir: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

// Go: verify the plan dir parent is writable before CreatePlan
plansDir := getPlansBaseDir()
if fi, err := os.Stat(plansDir); err != nil || !fi.IsDir() {
    return fmt.Errorf("plans dir %s missing", plansDir)
}
if err := syscall.Access(plansDir, os.O_RDWR); err != nil {
    return fmt.Errorf("plans dir not writable: %w", err)
}

Type guard

func dirWritable(path string) bool {
    fi, err := os.Stat(path)
    return err == nil && fi.IsDir() && unix.Access(path, unix.W_OK) == nil
}

Try / catch

plan, err := db.CreatePlan(ctx, orgId, projectId, userId, name)
if err != nil {
    if strings.Contains(err.Error(), "error initializing plan dir") {
        if _, statErr := os.Stat(planDirPath); statErr == nil {
            os.RemoveAll(planDirPath) // drop orphaned dir; DB tx already rolled back
        }
        return nil, fmt.Errorf("plan dir init failed; cleaned up and can retry: %w", err)
    }
    return nil, err
}

Prevention

When it happens

Trigger: Calling CreatePlan when the plan directory cannot be created (insufficient permissions on the storage root, disk full, path too long), when a directory for the same plan id already exists with conflicting contents, or when InitPlan's internal file writes fail mid-way.

Common situations: Read-only or full volume hosting plan data, running the server as a user without write access to the plan storage root, leftover directories from an earlier failed CreatePlan, or container storage limits being hit.

Related errors


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