gitbutlerapp/gitbutler · error · ExplainedRejection
Cannot {verb}: {rejected}:
Error message
Cannot {verb}: {rejected}: What it means
The full-form rejection error from but's utils: the operation was rejected due to RejectedChanges, the workspace projection loaded successfully, and write_report() appended a per-path report (paths, coarse reason, and which workspace commits/branches the hunks depend on) after the 'Cannot <verb>: N rejected changes:' header. This is the explanation, not just the failure.
Source
Thrown at crates/but/src/utils/rejection.rs:119
}
};
let (repo, ws) = (&repo, &ws);
let target_branch = match &target {
Target::Commit(commit) => branch_of_commit(ws, commit.commit_id, None),
Target::Branch(name) => Some(name.clone()),
Target::NewBranch(_) => None,
};
let changes = match explain_rejections(repo, ws, &rejected.0, target_branch.as_deref()) {
Ok(changes) => changes,
Err(other) => return other,
};
let mut message = format!("Cannot {verb}: {rejected}:\n");
// Writing to a String cannot fail.
let _ = write_report(&mut message, &changes, &target, target_branch.as_deref());
anyhow::Error::new(ExplainedRejection(message.trim_end().to_string()))
}
/// A single rejected change, enriched with the workspace dependencies that
/// explain why it could not be applied.
struct RejectedChange {
/// The worktree-relative path of the rejected change.
path: BString,
/// The coarse reason the change was rejected.
reason: RejectionReason,
/// The hunks of this change that depend on a commit in the workspace,
/// together with the commit/branch they depend on.
///
/// Empty when the rejection was not caused by a dependency, or when the
/// dependency could not be pinpointed to a specific hunk.
dependencies: Vec<HunkDependency>,
/// When a dependency rejection cannot be pinpointed to a hunk (adjacent
/// insertions, for example, do not intersect as ranges), the branches
/// whose workspace commits also touch this path — the likely dependency.View on GitHub (pinned to caf1f223d3)
Solutions
- Read the report body: each listed path names the commit/branch the change depends on; include that dependency in the operation (apply/move it too) or apply to a target that already contains it.
- Reorder operations so dependencies are applied before dependents.
- If the dependency is intentionally excluded, expect the rejection and choose a different operation (e.g. apply the whole stack).
- Use the listed worktree-relative paths to cross-check which files caused each hunk rejection.
Defensive patterns
Strategy: try-catch
Try / catch
try {
await api.applyChanges(...);
} catch (e) {
const m = String(e?.message ?? e);
if (/Cannot .*rejected changes:\n/.test(m)) {
const report = m.split('\n').slice(1).join('\n');
showDependencyReport(report); // lists paths + the commits they depend on
}
throw e;
} Prevention
- Parse the report body: each path names the commit/branch dependency to include.
- Apply dependent commits in topological order (dependencies first).
- When applying part of a stack, expect rejections for hunks whose context comes from excluded commits.
When it happens
Trigger: Applying changes whose hunks depend on commits outside the selected target: e.g. moving/applying a commit whose parent changes are not part of the target branch set, or editing files whose workspace dependencies are not included.
Common situations: Cherry-applying an old commit whose context lines only exist because of a commit not being applied; ordering issues when moving commits across stacks; partial application attempts of a series.
Related errors
- Cannot {verb}: {rejected}
- When using OpenRouter, you must provide a valid API key
- HTTP Error ${response.statusText}: ${text}
- Tearing off a branch requires a workspace common base
- Refusing to delete last named segment '{}' as it would leave
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/1a691c1412ecf2c0.
Report an issue: GitHub.