{"record":{"id":"ed761426433c785f","repo":"gitbutlerapp/gitbutler","slug":"could-not-open-projects-file-at-it-was-moved","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/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/gitbutler-project/src/controller.rs#L132-L168","documentation":"At startup the project controller tries to load the projects file; when loading fails, it renames the broken file to a backup path and bails with this message. The next launch starts fresh (projects must be re-added), and only when `max_attempts` backup files already exist does it give up entirely. The original parse error is included as `probably_file_load_err`.","triggerScenarios":"Loading a projects file that fails to parse — invalid content from a partial write, a crash during save, or external truncation — while fewer than `max_attempts` backups exist.","commonSituations":"Power loss or forced quit during project save; disk-full during write; cloud-sync tools (Dropbox & co) corrupting the config; hand edits to the projects file.","solutions":["Restart/refresh the app: the broken file was already moved aside and a fresh one is created — re-add your projects","If you need the old list, open the renamed backup file next to the original path and salvage entries manually","If restore reports the backup limit was hit, delete old backup files so a new one can be created","Fix the root cause (sync conflicts, unclean shutdowns, disk space) before re-adding projects"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// validate the projects file before the controller loads it\nlet raw = std::fs::read_to_string(&projects_path)?;\nserde_json::from_str::<Vec<Project>>(&raw)\n    .with_context(|| format!(\"projects file at {} is corrupt\", projects_path.display()))?;","typeGuard":null,"tryCatchPattern":"match Controller::load_all(&paths) {\n    Err(err) if err.to_string().contains(\"Could not open projects file\") => {\n        // app already quarantined the file; start fresh, optionally salvage from the backup\n    }\n    other => other,\n}","preventionTips":["Keep the projects directory out of cloud-sync tools","Let the app shut down cleanly so project saves complete","Keep occasional copies of the projects file if re-adding projects is costly"],"tags":["rust","gitbutler","projects","startup","corrupt-file","backup"],"backgroundTag":"corrupt-config-file","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-23T16:17:53.355Z"}