{"record":{"id":"be3daf1f51fa7e23","repo":"plandex-ai/plandex","slug":"error-reading-hash-file-v-be3daf","errorCode":null,"errorMessage":"error reading hash file: %v","messagePattern":"error reading hash file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/cli/lib/model_settings.go","lineNumber":46,"sourceCode":"\tHasLocalChanges           bool\n\tLocalModelPackSchemaRoles *shared.ModelPackSchemaRoles\n}\n\nfunc ModelSettingsCheckLocalChanges(path string) (ModelSettingsCheckLocalChangesResult, error) {\n\thashPath := path + \".hash\"\n\n\texists, err := fs.FileExists(path)\n\tif err != nil {\n\t\treturn ModelSettingsCheckLocalChangesResult{}, fmt.Errorf(\"error checking model settings file: %v\", err)\n\t}\n\n\tif !exists {\n\t\treturn ModelSettingsCheckLocalChangesResult{}, nil\n\t}\n\n\tlastSavedHash, err := os.ReadFile(hashPath)\n\tif err != nil && !os.IsNotExist(err) {\n\t\treturn ModelSettingsCheckLocalChangesResult{}, fmt.Errorf(\"error reading hash file: %v\", err)\n\t}\n\n\tlocalJsonData, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn ModelSettingsCheckLocalChangesResult{}, fmt.Errorf(\"error reading JSON file: %v\", err)\n\t}\n\n\tvar clientModelPackSchemaRoles *shared.ClientModelPackSchemaRoles\n\terr = json.Unmarshal(localJsonData, &clientModelPackSchemaRoles)\n\tif err != nil {\n\t\treturn ModelSettingsCheckLocalChangesResult{}, fmt.Errorf(\"error unmarshalling JSON file: %v\", err)\n\t}\n\n\tcurrentHash, err := clientModelPackSchemaRoles.ToModelPackSchemaRoles().Hash()\n\tif err != nil {\n\t\treturn ModelSettingsCheckLocalChangesResult{}, fmt.Errorf(\"error hashing model pack: %v\", err)\n\t}\n","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/cli/lib/model_settings.go#L28-L64","documentation":"ModelSettingsCheckLocalChanges reads <path>.hash to get the last-saved hash for comparison. A missing hash file is tolerated (os.IsNotExist is allowed); any other read error is wrapped with this message, meaning local-change detection cannot proceed.","triggerScenarios":"os.ReadFile on <settingsPath>.hash fails with a non-NotNotExist error: permission denied, path is a directory, or I/O error on the hash sidecar file.","commonSituations":"The .hash file exists but is unreadable (owned by another user, or created with restrictive perms); a directory named <file>.hash was created accidentally; EDR/antivirus blocking access to dotfiles.","solutions":["Check permissions on the .hash file from the wrapped error path; chmod to make it readable.","If a directory occupies the .hash path, remove it (the hash will be regenerated).","As a last resort, delete the .hash file so the next sync treats the file as unhashed and recreates it."],"exampleFix":"// before\n// (no pre-check)\n// after: ensure the hash sidecar is readable or absent before calling\nif info, err := os.Stat(hashPath); err == nil && info.IsDir() {\n    os.RemoveAll(hashPath)\n}","handlingStrategy":"validation","validationCode":"if info, err := os.Stat(settingsPath + \".hash\"); err == nil && info.IsDir() {\n    os.RemoveAll(settingsPath + \".hash\")\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n    if strings.Contains(err.Error(), \"reading hash file\") && !os.IsNotExist(errors.Unwrap(err)) {\n        return fmt.Errorf(\"hash sidecar unreadable at %s.hash — fix perms or delete it to regenerate: %w\", settingsPath, err)\n    }\n    return err\n}","preventionTips":["Treat a missing .hash file as normal; only fix errors for existing-but-unreadable ones.","Don't chmod dotfiles/lockfiles with root-only ownership.","Never create a directory where the .hash file is expected.","Delete a corrupt .hash sidecar to let the next sync regenerate it."],"tags":["filesystem","permissions","hash"],"backgroundTag":"file-read-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"}