{"record":{"id":"21d2f99d20aacabd","repo":"plandex-ai/plandex","slug":"error-writing-file-v","errorCode":null,"errorMessage":"error writing file: %v","messagePattern":"error writing file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/cli/lib/custom_models.go","lineNumber":151,"sourceCode":"}\n\nfunc WriteCustomModelsFile(path string, modelsInput *shared.ModelsInput) error {\n\terr := os.MkdirAll(filepath.Dir(path), 0755)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error creating directory: %v\", err)\n\t}\n\n\tclientModelsInput := modelsInput.ToClientModelsInput()\n\tclientModelsInput.PrepareUpdate()\n\n\tjsonData, err := json.MarshalIndent(clientModelsInput, \"\", \"  \")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error marshalling models: %v\", err)\n\t}\n\n\terr = os.WriteFile(path, jsonData, 0644)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error writing file: %v\", err)\n\t}\n\n\terr = SaveCustomModelsHash(path, modelsInput)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error saving hash file: %v\", err)\n\t}\n\n\treturn nil\n}\n\nfunc SaveCustomModelsHash(basePath string, modelsInput *shared.ModelsInput) error {\n\thashPath := basePath + \".hash\"\n\n\thash, err := modelsInput.Hash()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error hashing models: %v\", err)\n\t}\n","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/cli/lib/custom_models.go#L133-L169","documentation":"WriteCustomModelsFile calls os.WriteFile(path, jsonData, 0644) to persist custom-models.json. This error wraps the OS-level failure of that write — the JSON marshal already succeeded, so the problem is filesystem access or path validity at the Plandex home accounts directory.","triggerScenarios":"os.WriteFile failing because the target directory (~/.plandex/accounts/<userId>/) does not exist, the disk is full, permissions on the file/directory deny writing, or the path points somewhere unwritable.","commonSituations":"Read-only home directory or NFS mount; disk quota exceeded; custom-models.json owned by another user after running the CLI with sudo; accounts directory deleted manually.","solutions":["Check the wrapped error for 'permission denied' and fix ownership/permissions on ~/.plandex/accounts/<userId>/ (e.g. chown -R $USER ~/.plandex).","Verify free disk space (df -h) and clear space if the disk is full.","Ensure the accounts/<userId> directory exists; recreate it if it was deleted.","Avoid running the CLI as root/sudo, which creates root-owned files in the Plandex home dir."],"exampleFix":"// before\nsudo plandex models  # creates root-owned custom-models.json\n// after\nchown -R $(whoami) ~/.plandex\nplandex models","handlingStrategy":"try-catch","validationCode":"// Validate writability before calling\nimport \"os\"\nfunc canWrite(path string) bool {\n    dir := filepath.Dir(path)\n    if _, err := os.Stat(dir); err != nil { return false }\n    f, err := os.CreateTemp(dir, \".wtest\")\n    if err != nil { return false }\n    f.Close(); os.Remove(f.Name())\n    return true\n}\n// if !canWrite(path) { fix permissions/space first }","typeGuard":"func isWriteError(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"error writing file\") &&\n        !strings.Contains(err.Error(), \"hash\")\n}","tryCatchPattern":"if err := lib.WriteCustomModelsFile(path, input); err != nil {\n    if isWriteError(err) {\n        term.Error(\"Cannot write custom-models.json: \" + err.Error())\n        // surface os.* permission/disk hint to the user\n        return\n    }\n    return err\n}","preventionTips":["Check disk space (df -h) in environments running the CLI unattended.","Never run the CLI with sudo; it creates root-owned files under ~/.plandex.","Ensure ~/.plandex/accounts/<userId>/ exists and is writable by the current user.","Monitor for read-only remounts on NFS/network home directories."],"tags":["go","filesystem","write","permissions","custom-models"],"backgroundTag":"file-write-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"}