{"record":{"id":"1967abf3ff11980b","repo":"gitbutlerapp/gitbutler","slug":"repo-access-failed","errorCode":null,"errorMessage":"repo access failed","messagePattern":"repo access failed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but/src/command/legacy/setup.rs","lineNumber":656,"sourceCode":"            create_empty_initial_commit(&repo)?;\n\n            writeln!(\n                &mut progress as &mut dyn FmtWrite,\n                \"{}\",\n                t.success\n                    .paint(\"Initialized a new repository and created an empty first commit.\\n\")\n            )?;\n            return Ok(repo);\n        }\n    }\n\n    Err(anyhow::anyhow!(\"No git repository found.\"))\n}\n\nfn create_empty_initial_commit(repo: &gix::Repository) -> anyhow::Result<()> {\n    // In an unborn repo, this returns the well-known empty-tree id.\n    // (It works even if the empty tree object isn’t physically in the ODB.)\n    let empty_tree = repo.head_tree_id_or_empty().expect(\"repo access failed\"); // -> Id<'_>\n    let empty_tree = empty_tree.detach(); // -> ObjectId (optional; commit() accepts Into<ObjectId> anyway)\n\n    // No parents for the first commit. Update HEAD (writes through to refs/heads/main).\n    repo.commit(\n        \"HEAD\",\n        \"Initial empty commit\\n\",\n        empty_tree,\n        std::iter::empty::<gix::hash::ObjectId>(),\n    )?;\n\n    Ok(())\n}\n","sourceCodeStart":638,"sourceCodeEnd":669,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but/src/command/legacy/setup.rs#L638-L669","documentation":"create_empty_initial_commit() runs during interactive `but` setup after the user answers 'y' to initializing a new repository (setup.rs:612-651). repo.head_tree_id_or_empty() returns a Result: on an unborn HEAD it yields the well-known empty tree id, but it errors when the repository cannot be accessed (unreadable .git/HEAD, object-store failure). The expect(\"repo access failed\") turns that gix::Error into a panic, even though every other call site in the workspace propagates it with `?` (e.g. but-workspace/src/worktree.rs:22).","triggerScenarios":"Running the `but` setup flow in a directory with no git repository and confirming initialization, when reading the freshly created .git/HEAD fails: disk I/O error, permission denial, or antivirus/file-lock interference right after gix::init().","commonSituations":"Read-only or full filesystems, containers with restricted mounts, security software locking .git files immediately after creation, or partial gix::init() failures leaving a broken .git directory.","solutions":["Check filesystem permissions and free space in the target directory, remove the partial .git directory, and retry the setup","Verify the created repo is readable (cat .git/HEAD works) and no security software is locking .git","As a contributor: replace the expect with error propagation (see exampleFix) since the identical call is fallible everywhere else in the codebase"],"exampleFix":"// before\nlet empty_tree = repo.head_tree_id_or_empty().expect(\"repo access failed\");\n\n// after\nlet empty_tree = repo\n    .head_tree_id_or_empty()\n    .context(\"failed to read HEAD tree of the freshly initialized repository\")?;","handlingStrategy":"try-catch","validationCode":"// Fail fast before setup: prove the target dir can hold a readable file\nlet probe = current_dir.join(\".git-probe\");\nstd::fs::write(&probe, b\"x\")?;\nstd::fs::read_to_string(&probe)?;\nstd::fs::remove_file(&probe)?;","typeGuard":null,"tryCatchPattern":"// Propagate instead of panicking - same call is fallible everywhere else\nlet empty_tree = repo\n    .head_tree_id_or_empty()\n    .context(\"failed to read HEAD tree of the freshly initialized repository\")?;","preventionTips":["Treat head_tree_id_or_empty() as fallible: propagate with ? like the other 12 call sites in the repo","Check disk writability before running interactive repo initialization","Keep antivirus/backup exclusions for the repo directory in locked-down environments"],"tags":["rust","git","gix","unborn-repo","io","setup","panic"],"backgroundTag":"git-repository-io-error","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}