gitbutlerapp/gitbutler · error
No base branch configured
Error message
No base branch configured
What it means
The public `branch_land` (merge) entrypoint needs a configured base (target) branch for the GitButler workspace. `get_base_branch_data` returns `None` when the workspace has no base branch configured, and this error is raised. Outside a `gitbutler/workspace` the code path differs (that case is handled earlier with its own error), so this error specifically means: inside a workspace, but no base branch data exists.
Solutions
- Set the workspace's base/target branch (via the GitButler UI or `but` workspace target configuration, e.g. `but branch new --set-target` / project target setup).
- Verify `git config gitbutler.*` / workspace metadata contains a base branch, or re-initialize the workspace.
- Confirm you are inside a proper GitButler workspace (`gitbutler/workspace` branch exists) so the right code path runs.
- Fetch the remote first, then re-set the target so `refs/remotes/<remote>/<target>` resolves.
Example fix
// before but merge; // fails: no base branch configured // after but workspace target --set origin/main; // configure base branch first but merge;
Defensive patterns
Strategy: validation
Validate before calling
// confirm a base branch is configured before calling merge
let base = get_base_branch_data(ctx, perm)?;
if base.is_none() {
eprintln!("no base branch configured; set workspace target first");
return Ok(());
} Try / catch
match branch_land(ctx, ...) {
Err(e) if e.to_string().contains("No base branch configured") => {
prompt_user_to_set_target_branch()?;
}
other => other?,
} Prevention
- Set the workspace target/base branch right after workspace creation
- Check `but` workspace target configuration in setup scripts before merging
- Re-set the target after fetching if remote branches changed
When it happens
Trigger: Calling `but merge` / `branch_land` in a GitButler workspace whose base/target branch was never set (e.g. workspace created without choosing a target); base branch data was cleared from workspace metadata.
Common situations: Newly initialized workspace where the user never picked a target branch; workspace metadata corrupted or partially migrated; working with `but merge` before running the normal branch/apply flow that establishes the base.
Understand the failure class
Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.
Related errors
- merge conflict when computing workspace tree
- Ad-hoc (single-branch) branch moves are not supported…
- An octopus merge commits must have at least two parents
- Branch not found
- Branch ' ' cannot be created: the target commit ( ) already…
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/7abe634facb0fe81.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-api/src/land/mod.rs:192
pub fn branch_land(
ctx: &mut Context,
branch: String,
no_ff: bool,
whole_stack: bool,
) -> anyhow::Result<BranchLandResult> {
let base_branch = {
let mut guard = ctx.exclusive_worktree_access();
{
let (_repo, ws, _db) = ctx.workspace_and_db_with_perm(guard.read_permission())?;
if !ws.kind.has_managed_ref() {
bail!(
"`but merge` requires an active GitButler workspace (`gitbutler/workspace`). \
Switch into the workspace and try again."
);
}
}
crate::legacy::virtual_branches::get_base_branch_data(ctx, guard.write_permission())?
.ok_or_else(|| anyhow::anyhow!("No base branch configured"))?
};
let target_branch_name = base_branch.short_name.clone();
if target_branch_name.is_empty() {
bail!("Configured target branch has no branch name");
}
let fetch_remote_name = base_branch.remote_name.clone();
let push_remote_name = if base_branch.push_remote_name.is_empty() {
fetch_remote_name.clone()
} else {
base_branch.push_remote_name.clone()
};
if push_remote_name.is_empty() {
bail!("Configured target branch has no push remote");
}
// Triangular remotes (fetch remote != push remote) are out of scope for now: the post-land
// reconcile reads the fetch remote's tracking ref, so a push to a different remote would notView on GitHub (pinned to 58e5313667)