{"record":{"id":"85dda575c2efa3f6","repo":"plandex-ai/plandex","slug":"error-unmarshalling-current-plans-v2-json-v","errorCode":null,"errorMessage":"error unmarshalling current-plans-v2.json: %v","messagePattern":"error unmarshalling current-plans-v2\\.json: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/cli/lib/plans.go","lineNumber":29,"sourceCode":"\t\"sync\"\n)\n\nfunc 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)","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/cli/lib/plans.go#L11-L47","documentation":"WriteCurrentPlan reads the user's ~/.plandex/current-plans-v2.json cache to record which plan is currently checked out. If the file exists but cannot be parsed as JSON into types.CurrentPlanSettingsByAccount, the function aborts so it never overwrites a corrupt state file with new data. The wrapped %v carries the underlying json.Unmarshal detail (offset, type mismatch).","triggerScenarios":"os.ReadFile on HomeCurrentPlanPath succeeds (file exists), but json.Unmarshal into *types.CurrentPlanSettingsByAccount fails — i.e. malformed JSON, an incompatible schema from an older Plandex version (the file is 'v2'), or the file's top level is not a JSON object keyed by account id. Raised from the 'plandex cd' and 'plandex new' commands.","commonSituations":"A ~/.plandex directory synced/cloned from another machine; a crashed prior write left a truncated JSON file; the user hand-edited current-plans-v2.json and broke the syntax; downgrading the CLI so the v2 schema no longer parses.","solutions":["Inspect the file: cat ~/.plandex/current-plans-v2.json | python3 -m json.tool to confirm it is invalid JSON.","Back it up and delete it (mv ~/.plandex/current-plans-v2.json ~/.plandex/current-plans-v2.json.bak); WriteCurrentPlan treats a missing file as a fresh empty state and recreates it.","Fix the specific JSON defect reported by the wrapped %v (e.g. a truncated or hand-edited entry).","If the schema changed across CLI versions, upgrade or re-run to let the current CLI rewrite the file."],"exampleFix":"// before: corrupt file blocks everything\nplandex cd\n// error unmarshalling current-plans-v2.json: unexpected end of JSON input\n\n// after: remove the corrupt cache so it is rebuilt\nmv ~/.plandex/current-plans-v2.json ~/.plandex/current-plans-v2.json.bak\nplandex cd","handlingStrategy":"try-catch","validationCode":"f, err := os.Open(filepath.Join(os.Getenv(\"HOME\"), \".plandex\", \"current-plans-v2.json\"))\nif err == nil {\n\tdec := json.NewDecoder(f)\n\tvar probe types.CurrentPlanSettingsByAccount\n\tif err := dec.Decode(&probe); err != nil {\n\t\t// invalid JSON — quarantine before invoking the CLI\n\t\tos.Rename(path, path+\".bak\")\n\t}\n\tf.Close()\n}","typeGuard":"func isValidPlansJSON(path string) bool {\n\tb, err := os.ReadFile(path)\n\tif err != nil { return false }\n\tvar v types.CurrentPlanSettingsByAccount\n\treturn json.Unmarshal(b, &v) == nil\n}","tryCatchPattern":"if err := lib.WriteCurrentPlan(id); err != nil {\n\tif strings.Contains(err.Error(), \"error unmarshalling current-plans-v2.json\") {\n\t\tos.Rename(homePlansPath, homePlansPath+\".bak\") // reset state and retry once\n\t\terr = lib.WriteCurrentPlan(id)\n\t}\n}","preventionTips":["Never hand-edit ~/.plandex/current-plans-v2.json while the CLI is installed.","Avoid syncing ~/.plandex across machines with different CLI versions.","Validate the file with a JSON linter after manual edits or external tooling touches it.","Back up the file before upgrading or downgrading the CLI."],"tags":["cli","json","unmarshal","local-cache","state-file"],"backgroundTag":"json-unmarshal-failed","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"}