{"record":{"id":"bd7f6481aea35a0a","repo":"plandex-ai/plandex","slug":"error-checking-if-current-plans-v2-json-exists-v","errorCode":null,"errorMessage":"error checking if current-plans-v2.json exists: %v","messagePattern":"error checking if current-plans-v2\\.json exists: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/cli/lib/plans.go","lineNumber":32,"sourceCode":"func WriteCurrentPlan(id string) error {\n\tif fs.HomePlandexDir == \"\" {\n\t\treturn fmt.Errorf(\"HomePlandexDir not set\")\n\t}\n\n\tif CurrentProjectId == \"\" || HomeCurrentPlanPath == \"\" {\n\t\treturn fmt.Errorf(\"no current project\")\n\t}\n\n\tvar currentPlanSettingsByAccount *types.CurrentPlanSettingsByAccount\n\n\tbytes, err := os.ReadFile(HomeCurrentPlanPath)\n\tif err == nil {\n\t\terr = json.Unmarshal(bytes, &currentPlanSettingsByAccount)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error unmarshalling current-plans-v2.json: %v\", err)\n\t\t}\n\t} else if !os.IsNotExist(err) {\n\t\treturn fmt.Errorf(\"error checking if current-plans-v2.json exists: %v\", err)\n\t}\n\n\tif currentPlanSettingsByAccount == nil {\n\t\tcurrentPlanSettingsByAccount = &types.CurrentPlanSettingsByAccount{}\n\t}\n\n\tsettings := types.CurrentPlanSettings{\n\t\tId: id,\n\t}\n\n\t(*currentPlanSettingsByAccount)[auth.Current.UserId] = &settings\n\n\tbytes, err = json.Marshal(currentPlanSettingsByAccount)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error marshalling current plan: %v\", err)\n\t}\n\n\terr = os.WriteFile(HomeCurrentPlanPath, bytes, 0644)","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/cli/lib/plans.go#L14-L50","documentation":"WriteCurrentPlan attempts to read ~/.plandex/current-plans-v2.json; a missing file is tolerated, but any other read error (permissions, I/O failure) is a hard error because the function cannot know the current-plan state. This error wraps the raw os.ReadFile failure.","triggerScenarios":"os.ReadFile(HomeCurrentPlanPath) returns an error that is not os.ErrNotExist — e.g. EACCES on the file, EISDIR (the path is a directory), or a device I/O error. Triggered via 'plandex cd' or 'plandex new'.","commonSituations":"current-plans-v2.json exists but is unreadable after running as a different user (root-created file); the path was replaced by a directory; a broken symlink pointing to an inaccessible target; read-only or failing filesystem.","solutions":["Check permissions: ls -l ~/.plandex/current-plans-v2.json and chown/chmod it back to your user (chmod u+r).","Check what the path actually is (file vs directory vs broken symlink): file ~/.plandex/current-plans-v2.json.","If it was created by root/sudo, chown $(whoami) ~/.plandex/current-plans-v2.json or move it aside.","Verify HOME is correct and points at your own ~/.plandex directory."],"exampleFix":"// before: file owned by root, unreadable\nsudo plandex new\n// error checking if current-plans-v2.json exists: open ...: permission denied\n\n// after: restore ownership to the invoking user\nsudo chown $(whoami) ~/.plandex/current-plans-v2.json\nplandex new","handlingStrategy":"validation","validationCode":"path := filepath.Join(os.Getenv(\"HOME\"), \".plandex\", \"current-plans-v2.json\")\nif fi, err := os.Stat(path); err == nil && fi.IsDir() {\n\treturn fmt.Errorf(\"%s is a directory; remove it first\", path)\n}\nif f, err := os.Open(path); err == nil { f.Close() } else if !errors.Is(err, fs.ErrNotExist) {\n\treturn fmt.Errorf(\"state file unreadable (%v); fix permissions before running plandex\", err)\n}","typeGuard":"func stateFileReadable(path string) bool {\n\tf, err := os.Open(path)\n\tif err != nil { return os.IsNotExist(err) } // missing is OK\n\tf.Close()\n\treturn true\n}","tryCatchPattern":"if err := lib.WriteCurrentPlan(id); err != nil {\n\tif strings.Contains(err.Error(), \"error checking if current-plans-v2.json exists\") {\n\t\t// surface a permission fix hint or run with corrected ownership\n\t}\n}","preventionTips":["Never run plandex commands with sudo; it creates root-owned state files.","Keep ~/.plandex on a writable, local filesystem.","Check ls -l ~/.plandex after using sync/backup tools that can alter ownership.","Verify HOME points to your own user before running the CLI."],"tags":["cli","filesystem","read-error","permissions","state-file"],"backgroundTag":"permission-denied","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}