{"record":{"id":"bdc4b51fa125fe63","repo":"gitbutlerapp/gitbutler","slug":"could-not-open-projects-file-at-nit-was-moved-to-nreopen-or","errorCode":null,"errorMessage":"Could not open projects file at '{}'.\\nIt was moved to {}.\\nReopen or refresh the app to start fresh.\\nError was: {probably_file_load_err}","messagePattern":"Could not open projects file at '(.+?)'\\.\\\\nIt was moved to (.+?)\\.\\\\nReopen or refresh the app to start fresh\\.\\\\nError was: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/gitbutler-project/src/controller.rs","lineNumber":150,"sourceCode":"                let projects_path = self.local_data_dir.join(\"projects.json\");\n                let max_attempts = 255;\n                for round in 1..max_attempts {\n                    let backup_path = self\n                        .local_data_dir\n                        .join(format!(\"projects.json.maybe-broken-{round:02}\"));\n                    if backup_path.is_file() {\n                        continue;\n                    }\n\n                    if let Err(err) = std::fs::rename(&projects_path, &backup_path) {\n                        tracing::error!(\n                            \"Failed to rename {} to {} - application may fail to startup: {err}\",\n                            projects_path.display(),\n                            backup_path.display()\n                        );\n                    }\n\n                    bail!(\n                        \"Could not open projects file at '{}'.\\nIt was moved to {}.\\nReopen or refresh the app to start fresh.\\nError was: {probably_file_load_err}\",\n                        projects_path.display(),\n                        backup_path.display()\n                    );\n                }\n                bail!(\"There were already {max_attempts} backup project files - giving up\")\n            }\n        }\n    }\n}\n\nimpl Controller {\n    pub(crate) fn from_path(path: impl Into<PathBuf>) -> Self {\n        let path = path.into();\n        Self {\n            projects_storage: storage::Storage::from_path(&path),\n            local_data_dir: path,\n        }","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/gitbutler-project/src/controller.rs#L132-L168","documentation":"Thrown by `assure_app_can_startup_or_fix_it` when the projects database file (`projects.json`) cannot be loaded, and the self-healing step that moves the unreadable file to a backup path has completed. The app cannot start without a valid projects store, so it bails with a message telling the user where the file was moved and that restarting will create a fresh one.","triggerScenarios":"Startup calls `assure_app_can_startup_or_fix_it`; `projects.json` fails to parse/load (`probably_file_load_err`), the rename to a backup path succeeds, and this bail reports the moved location and original error.","commonSituations":"Projects file corrupted by a crash mid-write or full disk; hand-edited JSON with syntax errors; permissions problems after migrating machines; schema changes after a GitButler version upgrade.","solutions":["Reopen/refresh the app as the message says: it starts fresh with an empty projects file","Inspect the error text (`Error was: ...`) to confirm whether it was a parse error, permission issue, or missing file","Recover data from the backup file at the path shown in the message (fix its JSON and copy it back as `projects.json` before restarting)","Check disk space and file permissions in the app data directory if the problem recurs"],"exampleFix":"// corrupted projects.json\n// before: {\"projects\": [ {\"id\": 1, \"path\": \"C:\\\\repo\"  <- truncated\n// after: restore a valid backup over projects.json before launching:\n//   {\"projects\": [{\"id\": 1, \"path\": \"/home/user/repo\"}]}\n// or simply restart to get a fresh empty file","handlingStrategy":"try-catch","validationCode":"// pre-validate the projects file before app startup\nlet raw = fs::read_to_string(&projects_path)?;\nif serde_json::from_str::<serde_json::Value>(&raw).is_err() {\n    fs::rename(&projects_path, &backup_path)?; // quarantine, start fresh\n}","typeGuard":null,"tryCatchPattern":"match load_projects(&projects_path) {\n    Err(err) => {\n        eprintln!(\"Could not open projects file: {err}; moved to backup, starting fresh\");\n        Projects::default()\n    }\n    Ok(p) => p,\n}","preventionTips":["Do not hand-edit projects.json while the app is running","Keep free disk space in the app data directory","Back up the app data directory before upgrading GitButler","Fix JSON syntax in the backup file and restore it if project list data matters"],"tags":["config","startup","json","file-corruption"],"backgroundTag":"file-read-failed","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}