{"record":{"id":"fee80efea20ab0f7","repo":"plandex-ai/plandex","slug":"error-writing-hash-file-v","errorCode":null,"errorMessage":"error writing hash file: %v","messagePattern":"error writing hash file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/cli/lib/custom_models.go","lineNumber":172,"sourceCode":"\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\n\terr = os.WriteFile(hashPath, []byte(hash), 0644)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error writing hash file: %v\", err)\n\t}\n\n\treturn nil\n}\n\nfunc MustSyncCustomModels(path string, serverModelsInput *shared.ModelsInput) bool {\n\tterm.StartSpinner(\"\")\n\n\tjsonData, err := os.ReadFile(path)\n\tif err != nil {\n\t\tterm.OutputErrorAndExit(\"Error reading custom models file: %v\", err)\n\t\treturn false\n\t}\n\n\tclientModelsInput, err := schema.ValidateModelsInputJSON(jsonData)\n\tif err != nil {\n\t\tterm.StopSpinner()\n\t\tcolor.New(color.Bold, term.ColorHiRed).Println(\"🚨 Error validating custom models file\")","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/cli/lib/custom_models.go#L154-L190","documentation":"SaveCustomModelsHash writes the computed hash to <basePath>.hash (e.g. custom-models.json.hash) with os.WriteFile(..., 0644). This error is the OS-level write failure for the hash file; the hash itself was computed successfully. Consequence: custom-models.json may exist without a matching hash, causing subsequent syncs to treat local state as changed.","triggerScenarios":"os.WriteFile failing on the hash path because the directory is missing, permissions deny writing, or disk is full — same conditions as the JSON write but specifically on the .hash file.","commonSituations":"Read-only filesystem; quota exceeded; .hash file owned by root after sudo usage; accounts directory manually cleaned while file handle expectations remain.","solutions":["Check the wrapped error for 'permission denied' and correct ownership: chown -R $(whoami) ~/.plandex.","Free disk space if the disk/quota is full.","Remove a corrupt or root-owned custom-models.json.hash and retry the models command.","Re-run the custom models write so the JSON file and hash are written together consistently."],"exampleFix":"// before\n-rw-r--r-- 1 root root custom-models.json.hash  # unwritable by user\n// after\nsudo rm ~/.plandex/accounts/<userId>/custom-models.json.hash\nplandex models  # rewrites hash as current user","handlingStrategy":"try-catch","validationCode":"// Ensure the hash file location is writable before syncing\nhp := path + \".hash\"\nif f, err := os.OpenFile(hp, os.O_WRONLY|os.O_CREATE, 0644); err != nil {\n    // abort: hash file not writable\n} else {\n    f.Close()\n}","typeGuard":"func isHashWriteError(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"error writing hash file\")\n}","tryCatchPattern":"if err := lib.WriteCustomModelsFile(path, input); err != nil {\n    if isHashWriteError(err) {\n        term.Error(\"Hash file write failed; delete \" + path + \".hash and retry\")\n        return\n    }\n    return err\n}","preventionTips":["Ensure the owning user matches the user running the CLI (avoid sudo).","Check quota/disk space before large model-pack updates.","If a hash write fails, delete the .hash file so sync doesn't compare against stale data.","Keep ~/.plandex on a local, non-read-only filesystem."],"tags":["go","filesystem","write","hash","permissions"],"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"}