{"record":{"id":"bea9860cad47696c","repo":"plandex-ai/plandex","slug":"error-writing-current-plan-settings-v","errorCode":null,"errorMessage":"error writing current plan settings: %v","messagePattern":"error writing current plan settings: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/cli/lib/plans.go","lineNumber":156,"sourceCode":"\n\texistingSettings := (*settingsByAccount)[auth.Current.UserId]\n\n\tif existingSettings == nil {\n\t\texistingSettings = &types.PlanSettings{}\n\t}\n\n\texistingSettings.Branch = branch\n\t(*settingsByAccount)[auth.Current.UserId] = existingSettings\n\n\tbytes, err = json.Marshal(settingsByAccount)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error marshalling current plan settings: %v\", err)\n\t}\n\n\terr = os.WriteFile(path, bytes, 0644)\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error writing current plan settings: %v\", err)\n\t}\n\n\tCurrentBranch = branch\n\n\treturn nil\n}\n\nfunc GetCurrentBranchNamesByPlanId(planIds []string) (map[string]string, error) {\n\tif fs.HomePlandexDir == \"\" {\n\t\treturn nil, fmt.Errorf(\"HomePlandexDir not set\")\n\t}\n\n\tif CurrentProjectId == \"\" || HomeCurrentPlanPath == \"\" {\n\t\treturn nil, fmt.Errorf(\"no current project\")\n\t}\n\n\tvar mu sync.Mutex\n\tbranches := make(map[string]string)","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/cli/lib/plans.go#L138-L174","documentation":"This is the final write step of WriteCurrentBranch: os.WriteFile(path, bytes, 0644) persists settings-v2.json. If the write fails — permissions, disk full, read-only filesystem, path is a directory — the OS error is wrapped as 'error writing current plan settings: %v'. Note the in-memory CurrentBranch global is only updated after this succeeds, so a failure leaves branch state unchanged.","triggerScenarios":"os.WriteFile fails on ~/.plandex/<projectId>/<planId>/settings-v2.json: permission denied, read-only mount, no space left on device, or a directory exists at that exact path.","commonSituations":"Home dir quota exceeded or disk full; ~/.plandex ownership changed by running the CLI with sudo; a directory mistakenly created at settings-v2.json; network home dirs (NFS) gone read-only after a disconnect.","solutions":["Read the wrapped OS error and address it: free disk space, fix permissions (chown/chmod), or remove a conflicting directory.","Verify ~/.plandex is writable by the current user: touch ~/.plandex/<project>/<plan>/settings-v2.json.test","If on a network mount, reconnect/remount read-write, then rerun the checkout/branch command."],"exampleFix":"// error: ... no space left on device\n$ df -h ~\n$ rm -rf ~/tmp-cleanup   # free space\n$ plandex checkout main","handlingStrategy":"try-catch","validationCode":"dir := filepath.Join(fs.HomePlandexDir, lib.CurrentProjectId, lib.CurrentPlanId)\nif err := os.WriteFile(filepath.Join(dir, \".write-test\"), []byte(\"ok\"), 0644); err != nil {\n    return fmt.Errorf(\"~/.plandex not writable: %w\", err)\n}\nos.Remove(filepath.Join(dir, \".write-test\"))","typeGuard":null,"tryCatchPattern":"if err := lib.WriteCurrentBranch(branch); err != nil {\n    var pe *os.PathError\n    if errors.As(err, &pe) && errors.Is(pe.Err, syscall.ENOSPC) {\n        return fmt.Errorf(\"disk full: free space and retry\")\n    }\n    if errors.Is(err, os.ErrPermission) {\n        return fmt.Errorf(\"run: chown -R $USER ~/.plandex\")\n    }\n    return err\n}","preventionTips":["Monitor disk quota/space on the home filesystem.","Never run the CLI with sudo; fix ownership afterwards with chown if you did.","On NFS/network homes, confirm the mount is read-write before branch operations."],"tags":["go","filesystem","permissions","disk"],"backgroundTag":"write-failed-permission-denied","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}