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

When reading settings-v2.json, WriteCurrentBranch tolerates os.IsNotExist but treats any other read error (permission denied, path is a directory, I/O error) as fatal, wrapping it as 'error checking if settings-v2.json exists: %v'. This distinguishes 'no settings yet' from 'cannot even stat/read the file'.

Source

Thrown at app/cli/lib/plans.go:132

	err := os.MkdirAll(dir, os.ModePerm)

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

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

	var settingsByAccount *types.PlanSettingsByAccount

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

	if settingsByAccount == nil {
		settingsByAccount = &types.PlanSettingsByAccount{}
	}

	existingSettings := (*settingsByAccount)[auth.Current.UserId]

	if existingSettings == nil {
		existingSettings = &types.PlanSettings{}
	}

	existingSettings.Branch = branch
	(*settingsByAccount)[auth.Current.UserId] = existingSettings

	bytes, err = json.Marshal(settingsByAccount)
	if err != nil {
		return fmt.Errorf("error marshalling current plan settings: %v", err)

View on GitHub (pinned to e2d772072e)

Solutions

  1. Read the wrapped OS error; for permission issues run chmod u+rw (or chown back to your user) on the file/dir.
  2. If settings-v2.json is a directory, remove/rename it so the CLI can write a file there.
  3. Check filesystem health (mount flags, dmesg) if errors indicate I/O problems.

Example fix

// error: ... permission denied
$ ls -la ~/.plandex/<project>/<plan>/settings-v2.json
$ sudo chown -R $USER ~/.plandex && chmod -R u+rw ~/.plandex
$ plandex checkout main
Defensive patterns

Strategy: try-catch

Validate before calling

path := filepath.Join(fs.HomePlandexDir, lib.CurrentProjectId, lib.CurrentPlanId, "settings-v2.json")
if _, err := os.Stat(path); err != nil && !os.IsNotExist(err) {
    return fmt.Errorf("cannot access settings-v2.json: %w", err)
}

Try / catch

if err := lib.WriteCurrentBranch(branch); err != nil {
    if strings.Contains(err.Error(), "error checking if settings-v2.json exists") {
        if errors.Is(err, os.ErrPermission) {
            return fmt.Errorf("fix ownership: chown -R $USER ~/.plandex")
        }
        return err
    }
    return nil
}

Prevention

When it happens

Trigger: os.ReadFile on settings-v2.json fails with a non-ENOENT error: permission denied, the path exists as a directory named settings-v2.json, symlink loop, or underlying disk I/O error.

Common situations: settings-v2.json owned by root after a sudo run; someone created a directory named settings-v2.json; filesystem mounted read-only or failing; backup/restore tools leaving wrong permissions.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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