gitbutlerapp/gitbutler · error
Could not open projects file at '{}'. It was moved to {}. Re
Error message
Could not open projects file at '{}'.
It was moved to {}.
Reopen or refresh the app to start fresh.
Error was: {probably_file_load_err} What it means
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`.
Source
Thrown at crates/gitbutler-project/src/controller.rs:150
let projects_path = self.local_data_dir.join("projects.json");
let max_attempts = 255;
for round in 1..max_attempts {
let backup_path = self
.local_data_dir
.join(format!("projects.json.maybe-broken-{round:02}"));
if backup_path.is_file() {
continue;
}
if let Err(err) = std::fs::rename(&projects_path, &backup_path) {
tracing::error!(
"Failed to rename {} to {} - application may fail to startup: {err}",
projects_path.display(),
backup_path.display()
);
}
bail!(
"Could not open projects file at '{}'.\nIt was moved to {}.\nReopen or refresh the app to start fresh.\nError was: {probably_file_load_err}",
projects_path.display(),
backup_path.display()
);
}
bail!("There were already {max_attempts} backup project files - giving up")
}
}
}
}
impl Controller {
pub(crate) fn from_path(path: impl Into<PathBuf>) -> Self {
let path = path.into();
Self {
projects_storage: storage::Storage::from_path(&path),
local_data_dir: path,
}View on GitHub (pinned to caf1f223d3)
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
Defensive patterns
Strategy: fallback
Validate before calling
// validate the projects file before the controller loads it
let raw = std::fs::read_to_string(&projects_path)?;
serde_json::from_str::<Vec<Project>>(&raw)
.with_context(|| format!("projects file at {} is corrupt", projects_path.display()))?; Try / catch
match Controller::load_all(&paths) {
Err(err) if err.to_string().contains("Could not open projects file") => {
// app already quarantined the file; start fresh, optionally salvage from the backup
}
other => other,
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Failed to communicate with LM Studio server: ${error instanc
- Invalid response: ${JSON.stringify(result)}
- When using GitButler's API to summarize code, you must be lo
- When using LM Studio, you must provide a valid endpoint
- When using OpenAI in a bring your own key configuration, you
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/ed761426433c785f.
Report an issue: GitHub.