{"record":{"id":"a568dd769c55577b","repo":"plandex-ai/plandex","slug":"error-saving-model-pack-roles-hash-v","errorCode":null,"errorMessage":"error saving model pack roles hash: %v","messagePattern":"error saving model pack roles hash: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/cli/lib/model_settings.go","lineNumber":95,"sourceCode":"\t}\n\n\tmodelPackSchemaRoles := originalSettings.GetModelPack().ToModelPackSchema().ModelPackSchemaRoles\n\n\tclientModelPackRoles := modelPackSchemaRoles.ToClientModelPackSchemaRoles()\n\n\tbytes, err := json.MarshalIndent(clientModelPackRoles, \"\", \"  \")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error marshalling model pack: %v\", err)\n\t}\n\n\terr = os.WriteFile(path, bytes, 0644)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error writing JSON file: %v\", err)\n\t}\n\n\terr = SaveModelPackRolesHash(path, &modelPackSchemaRoles)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error saving model pack roles hash: %v\", err)\n\t}\n\n\treturn nil\n}\n\nfunc SaveModelPackRolesHash(basePath string, serverModelPack *shared.ModelPackSchemaRoles) error {\n\thashPath := basePath + \".hash\"\n\n\thash, err := serverModelPack.Hash()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error hashing model pack: %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","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/cli/lib/model_settings.go#L77-L113","documentation":"After writing model-settings.json, WriteModelSettingsFile calls SaveModelPackRolesHash to persist a hash sidecar (<path>.hash) used later to detect local edits. Any error from that helper is re-wrapped as 'error saving model pack roles hash: %v'. The JSON file may already have been written successfully when this fires, leaving the pair inconsistent.","triggerScenarios":"SaveModelPackRolesHash fails because ModelPackSchemaRoles.Hash() errors or because writing the <path>.hash file fails (read-only directory, permissions, disk full).","commonSituations":"Hash file locked or owned by another user; plan directory made read-only after the JSON write succeeded; plandex-shared hashing failure after a version upgrade.","solutions":["Read the wrapped cause: if it's a hash-write OS error, fix ~/.plandex directory permissions","If the hash is inconsistent, delete both model-settings.json and model-settings.json.hash and re-save model settings","Free disk space if the write failed with ENOSPC","Match CLI and plandex-shared versions if the underlying Hash() call failed"],"exampleFix":"// before\nerror saving model pack roles hash: open .../model-settings.json.hash: permission denied\n// after\nchmod u+w ~/.plandex/<planId> && plandex update-model-settings","handlingStrategy":"try-catch","validationCode":"// ensure both the settings file and hash sidecar path are writable beforehand\nfor _, p := range []string{path, path + \".hash\"} {\n    if f, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE, 0o644); err != nil {\n        return fmt.Errorf(\"%s not writable: %w\", p, err)\n    } else { f.Close() }\n}","typeGuard":null,"tryCatchPattern":"if err := lib.WriteModelSettingsFile(path, settings); err != nil {\n    if strings.Contains(err.Error(), \"error saving model pack roles hash\") {\n        // JSON may be written but hash stale: remove both files and re-save\n    }\n    return err\n}","preventionTips":["Keep the .json and .hash files' permissions identical","After any hash-save failure, delete both files to stay consistent","Ensure the directory stays writable for the whole operation","Upgrade plandex-shared together with the CLI"],"tags":["go","filesystem","hash","sidecar"],"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-14T00:17:10.932Z"}