{"record":{"id":"abac5ab4a1559ece","repo":"plandex-ai/plandex","slug":"error-writing-convo-message-description-v","errorCode":null,"errorMessage":"error writing convo message description: %v","messagePattern":"error writing convo message description: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/db/plan_helpers.go","lineNumber":346,"sourceCode":"\n\tnow := time.Now()\n\n\tif description.Id == \"\" {\n\t\tdescription.Id = uuid.New().String()\n\t\tdescription.CreatedAt = now\n\t}\n\tdescription.UpdatedAt = now\n\n\tbytes, err := json.Marshal(description)\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error marshalling convo message description: %v\", err)\n\t}\n\n\terr = os.WriteFile(filepath.Join(descriptionsDir, description.Id+\".json\"), bytes, os.ModePerm)\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error writing convo message description: %v\", err)\n\t}\n\n\treturn nil\n}\n\nfunc DeleteDraftPlans(orgId, projectId, userId string) error {\n\tres, err := Conn.Query(\"DELETE FROM plans WHERE project_id = $1 AND owner_id = $2 AND name = 'draft' RETURNING id;\", projectId, userId)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error deleting draft plans: %v\", err)\n\t}\n\n\tdefer res.Close()\n\n\t// get ids\n\tvar ids []string\n\n\tfor res.Next() {\n\t\tvar id string","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/plan_helpers.go#L328-L364","documentation":"After marshaling, StoreDescription writes the JSON to descriptionsDir/<id>.json via os.WriteFile. This error wraps any OS-level failure of that write: permissions, missing directory, disk full, or I/O errors.","triggerScenarios":"os.WriteFile(filepath.Join(descriptionsDir, description.Id+\".json\"), bytes, os.ModePerm) fails: directory was removed between MkdirAll and the write, permission denied, ENOSPC (disk full), description.Id is empty producing \".json\", or read-only filesystem.","commonSituations":"Disk quota exceeded on the storage volume; concurrent DeletePlanDir removing the plan directory while a description write is in flight; empty Id due to upstream data bug; container filesystem mounted read-only after crash recovery.","solutions":["Check the wrapped OS error (ENOSPC, EACCES) and fix storage capacity/permissions","Verify description.Id is non-empty before writing","Ensure directory creation and write use consistent, non-racy lifecycle (don't delete plan dir concurrently)","Use a safer permission mode (e.g. 0o644) instead of os.ModePerm on the file","Mount the storage volume read-write and monitor disk usage"],"exampleFix":"// before\nif description.Id == \"\" {\n    // proceeds and writes \".json\"\n}\nerr = os.WriteFile(filepath.Join(descriptionsDir, description.Id+\".json\"), bytes, os.ModePerm)\n// after\nif description.Id == \"\" {\n    return fmt.Errorf(\"cannot store description: empty id\")\n}\nif err := os.WriteFile(filepath.Join(descriptionsDir, description.Id+\".json\"), bytes, 0o644); err != nil {\n    return fmt.Errorf(\"error writing convo message description: %w\", err)\n}","handlingStrategy":"validation","validationCode":"if description.Id == \"\" {\n    return fmt.Errorf(\"description id is empty\")\n}\nif err := validateDirWritable(descriptionsDir); err != nil {\n    return err\n}","typeGuard":null,"tryCatchPattern":"if err := StoreDescription(desc); err != nil {\n    var pe *fs.PathError\n    if errors.As(err, &pe) && errors.Is(pe.Err, syscall.ENOSPC) {\n        // free disk space / alert ops\n    }\n    return err\n}","preventionTips":["Reject empty plan/description ids before persistence","Monitor disk usage and quotas on the storage volume","Don't delete plan dirs concurrently with writes","Use explicit file modes (0o644) rather than os.ModePerm"],"tags":["filesystem","io","disk","go"],"backgroundTag":"file-write-failed","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"}