gitbutlerapp/gitbutler · error
Invalid source: expected an uncommitted file or branch
Error message
Invalid source: expected an uncommitted file or branch
What it means
`but absorb` resolves its source argument into an AbsorptionTarget (an uncommitted file assignment or a branch/lane). If the resolved value falls into no known arm of the match — i.e. the argument named something that is neither an uncommitted file nor a branch — the handler bails with this generic invalid-source error.
Solutions
- Check `but status` and pass an uncommitted file path or an existing branch name
- Commit or note that the file's changes are already absorbed if it is no longer uncommitted
- Spell the branch exactly (local branch names, not remotes/origin refs)
Example fix
// before but absorb origin/feature-x # remote ref, not a branch target // after but absorb feature-x
Defensive patterns
Strategy: validation
Validate before calling
function assertAbsorbableSource(name, uncommittedFiles, localBranches) {
if (!uncommittedFiles.includes(name) && !localBranches.includes(name)) {
throw new Error(`Invalid absorb source: ${name} is not an uncommitted file or branch`);
}
} Type guard
const isValidSource = (name, files, branches) => files.includes(name) || branches.includes(name);
Try / catch
try {
await exec(`but absorb ${src}`);
} catch (e) {
if (e.message.includes('Invalid source')) {
console.error('Pick a name from but status (uncommitted file or branch)');
} else throw e;
} Prevention
- Source arguments from live `but status` output, not from memory
- Re-check state after commits/stashes — previously valid names become invalid
- Use local branch names, not remote refs
When it happens
Trigger: Passing an argument to `but absorb` that resolves to something other than an uncommitted file or a branch: e.g. a committed-but-clean file path, a ref that is not a local branch, an empty selection enum arm, or a stale name for a file whose changes were already committed/stashed.
Common situations: Naming a file whose changes were already committed (no longer uncommitted); typos in branch names; trying to absorb against a remote-only ref; running absorb after the working tree changed so a previously valid name no longer resolves.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Aborting due to empty branch name
- Bare repositories are not supported.
- Branch ' ' not found
- Branch ' ' not found when checking for conflicts
- Branch " " has no conflicted commits.
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/7e7e22788871100c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but/src/command/legacy/absorb.rs:89
})
.transpose()?;
let target = if let Some(source) = source {
match source {
CliId::UncommittedHunkOrFile(UncommittedHunkOrFile { hunks, .. }) => {
// Absorb this particular file
AbsorptionTarget::Hunks {
hunks: hunks.map(|id_and_hunk| id_and_hunk.hunk).into(),
}
}
CliId::Branch(branch) => {
// Absorb everything that is assigned to this lane
AbsorptionTarget::Branch {
branch_name: branch.name,
}
}
_ => {
anyhow::bail!("Invalid source: expected an uncommitted file or branch");
}
}
} else {
// Try to absorb everything uncommitted
Default::default()
};
// TODO: Ideally, there's a simpler way of getting the worktree changes without passing the context to it.
// At this time, the context is passed pretty deep into the function.
let absorption_plan =
but_api::legacy::absorb::absorption_plan_with_perm(ctx, target, guard.write_permission())?;
// Absorbing into a landed commit entangles the new change with an entire
// already-merged commit, which conflicts on the next `but pull`. Drop such
// plan entries and tell the user, instead of silently amending them.
let merged = MergedUpstream::from_ctx(ctx, allow_merged)?;
let Some((absorption_plan, skipped_merged)) =
drop_landed_absorptions(absorption_plan, &merged, out)?View on GitHub (pinned to 58e5313667)