{"record":{"id":"d405290c6262a60a","repo":"gitbutlerapp/gitbutler","slug":"cannot-currently-work-in-repositories-without-a-worktree","errorCode":null,"errorMessage":"Cannot currently work in repositories without a worktree","messagePattern":"Cannot currently work in repositories without a worktree","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/gitbutler-repo/src/commands.rs","lineNumber":364,"sourceCode":"\n    let tree = repo.find_commit(commit_id)?.tree()?;\n\n    Ok(match tree.lookup_entry_by_path(relative_path)? {\n        Some(entry) => {\n            let blob = repo.find_blob(entry.id())?;\n            FileInfo::from_content(relative_path, &blob.data)\n        }\n        None => FileInfo::deleted(),\n    })\n}\n\n/// Read `path` from the checkout of `repo`, see [`RepoCommands::read_file_from_workspace()`].\n/// `path` can be relative or absolute, and is validated to be inside the worktree.\n/// A linked worktree opened from disk reads the same way as the main worktree.\npub fn read_worktree_file(repo: &gix::Repository, path: &Path) -> Result<FileInfo> {\n    let workdir = repo\n        .workdir()\n        .ok_or_else(|| anyhow!(\"Cannot currently work in repositories without a worktree\"))?;\n    let canonical_workdir = gix::path::realpath(workdir)?;\n    let path = gix::path::realpath(canonical_workdir.join(path))?;\n    // Double-check that the path is still in the worktree - this might not be the case\n    // if it was absolute to begin with, or leads through symlinks.\n    let relative_path = match path.strip_prefix(&canonical_workdir) {\n        Ok(relative_path) => relative_path.to_owned(),\n        Err(_) => {\n            bail!(\n                \"Path to read from at '{}' isn't in the worktree directory '{}'\",\n                path.display(),\n                canonical_workdir.display()\n            );\n        }\n    };\n\n    // Refuse `.git` in every spelling an OS can map onto it (`.GIT`,\n    // `GIT~1`, `.git.`). Runs before the stat: `.git` can be a file\n    // (linked worktrees) and must be refused all the same.","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/gitbutler-repo/src/commands.rs#L346-L382","documentation":"read_worktree_file() in gitbutler-repo reads a file from the repository's checked-out working tree. gix's Repository::workdir() returns None for bare repositories, and reading workspace files from a bare repo is unsupported, so this error is raised.","triggerScenarios":"Calling get_workspace_file_from_source or read_file_from_workspace (which call read_worktree_file) with a repository handle opened from a bare git dir — e.g. a .git directory opened directly or a bare clone.","commonSituations":"Tauri commands invoked against a project whose repo was opened from its git dir; pointing GitButler at a bare remote mirror; tests constructing a gix::Repository from a bare path.","solutions":["Open the repository from a non-bare checkout so workdir() returns Some.","If you need file contents from a bare repo, read from an object/tree via gix instead of the worktree API.","Re-clone as a normal working copy and register that path as the project."],"exampleFix":"// before\nlet repo = gix::open(\"/srv/origin.git\")?;          // bare\nread_file_from_workspace(&repo, \"src/main.rs\")?;\n// after\nlet repo = gix::open(\"~/work/myrepo\")?;            // non-bare checkout\nread_file_from_workspace(&repo, \"src/main.rs\")?;","handlingStrategy":"validation","validationCode":"if repo.workdir().is_none() {\n    return Err(anyhow!(\"repo is bare; cannot read workspace files\"));\n}","typeGuard":"fn has_worktree(repo: &gix::Repository) -> bool { repo.workdir().is_some() }","tryCatchPattern":"match read_file_from_workspace(&repo, path) {\n    Err(e) if e.to_string().contains(\"without a worktree\") => read_from_tree_fallback(&repo, path),\n    other => other,\n}","preventionTips":["Check repo.workdir().is_some() before any worktree-file API.","Open repos from the checkout, not the bare git dir.","For bare repos, read blobs via tree/object APIs instead."],"tags":["git","bare-repository","worktree"],"backgroundTag":"unsupported-operation","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"}