plandex-ai/plandex · error

error checking if settings-v2.json exists: %v

Error message

error checking if settings-v2.json exists: %v

What it means

loadCurrentBranch stats <HomeCurrentProjectDir>/<CurrentPlanId>/settings-v2.json and wraps any stat error that is NOT 'file does not exist' as 'error checking if settings-v2.json exists: %v'. It distinguishes a genuinely failed stat (permissions, path issues) from a missing file (which returns nil).

Source

Thrown at app/cli/lib/current.go:187

		}
	}
}

func loadCurrentBranch() error {
	// Load plan-specific settings
	if CurrentPlanId == "" {
		return fmt.Errorf("no current plan")
	}

	path := filepath.Join(HomeCurrentProjectDir, CurrentPlanId, "settings-v2.json")

	// Check if the file exists
	_, err := os.Stat(path)

	if os.IsNotExist(err) {
		return nil
	} else if err != nil {
		return fmt.Errorf("error checking if settings-v2.json exists: %v", err)
	}

	fileBytes, err := os.ReadFile(path)
	if err != nil {
		term.OutputErrorAndExit("error reading settings-v2.json: %v", err)
	}

	var settingsByAccount types.PlanSettingsByAccount
	err = json.Unmarshal(fileBytes, &settingsByAccount)
	if err != nil {
		term.OutputErrorAndExit("error unmarshalling settings-v2.json: %v", err)
	}
	settings := settingsByAccount[auth.Current.UserId]

	if settings == nil {
		return nil
	}

View on GitHub (pinned to e2d772072e)

Solutions

  1. Check permissions on HomeCurrentProjectDir/<CurrentPlanId>/ and fix with chmod/chown
  2. Verify the path is a directory and settings-v2.json is a regular readable file
  3. Inspect the wrapped stat error (%v) for the exact OS reason
  4. Recreate the plan directory/settings file if the state is corrupted

Example fix

// before
_, err := os.Stat(path)
if err != nil && !os.IsNotExist(err) {
    return fmt.Errorf("error checking if settings-v2.json exists: %v", err)
}
// after: caller-side preflight
if info, err := os.Stat(planDir); err != nil || !info.IsDir() {
    term.OutputErrorAndExit("plan dir unreadable: %v — check permissions", planDir)
}
Defensive patterns

Strategy: validation

Validate before calling

planDir := filepath.Join(HomeCurrentProjectDir, CurrentPlanId)
if info, err := os.Stat(planDir); err != nil || !info.IsDir() {
    return fmt.Errorf("plan directory unavailable: %s (%v)", planDir, err)
}

Type guard

func settingsReadable(path string) bool {
    info, err := os.Stat(path)
    return err == nil || os.IsNotExist(err) // only these two are handleable
}

Try / catch

current, err := MustLoadCurrentPlan()
if err != nil && strings.Contains(err.Error(), "error checking if settings-v2.json exists") {
    fmt.Fprintf(os.Stderr, "check permissions on %s: %v\n", HomeCurrentProjectDir, err)
    os.Exit(1)
}

Prevention

When it happens

Trigger: os.Stat on the settings-v2.json path returns an error that is neither nil nor os.IsNotExist — e.g. permission denied on the plan directory, I/O error, path is not a directory, or a symlink loop.

Common situations: Restrictive file permissions on ~/.<app>/current-project/<planId>/; the plan directory was replaced by a file; disk/network home-directory issues (e.g. NFS/roaming profiles); antivirus locking the path on Windows.

Related errors


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