{"record":{"id":"21496e611bb73e4f","repo":"gitbutlerapp/gitbutler","slug":"cannot-verb-rejected-n-report","errorCode":null,"errorMessage":"Cannot {verb}: {rejected}:\\n{report}","messagePattern":"Cannot (.+?): (.+?):\\\\n(.+?)","errorType":"error_code","errorClass":"ExplainedRejection","httpStatus":null,"severity":"warning","filePath":"crates/but/src/utils/rejection.rs","lineNumber":119,"sourceCode":"        }\n    };\n    let (repo, ws) = (&repo, &ws);\n\n    let target_branch = match &target {\n        Target::Commit(commit) => branch_of_commit(ws, commit.commit_id, None),\n        Target::Branch(name) => Some(name.clone()),\n        Target::NewBranch(_) => None,\n    };\n\n    let changes = match explain_rejections(repo, ws, &rejected.0, target_branch.as_deref()) {\n        Ok(changes) => changes,\n        Err(other) => return other,\n    };\n\n    let mut message = format!(\"Cannot {verb}: {rejected}:\\n\");\n    // Writing to a String cannot fail.\n    let _ = write_report(&mut message, &changes, &target, target_branch.as_deref());\n    anyhow::Error::new(ExplainedRejection(message.trim_end().to_string()))\n}\n\n/// A single rejected change, enriched with the workspace dependencies that\n/// explain why it could not be applied.\nstruct RejectedChange {\n    /// The worktree-relative path of the rejected change.\n    path: BString,\n    /// The coarse reason the change was rejected.\n    reason: RejectionReason,\n    /// The hunks of this change that depend on a commit in the workspace,\n    /// together with the commit/branch they depend on.\n    ///\n    /// Empty when the rejection was not caused by a dependency, or when the\n    /// dependency could not be pinpointed to a specific hunk.\n    dependencies: Vec<HunkDependency>,\n    /// When a dependency rejection cannot be pinpointed to a hunk (adjacent\n    /// insertions, for example, do not intersect as ranges), the branches\n    /// whose workspace commits also touch this path — the likely dependency.","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but/src/utils/rejection.rs#L101-L137","documentation":"The primary explained-rejection error: after an operation (assign/apply) is rolled back, `explain_after_rollback` builds a human-readable report of each rejected change with the workspace dependencies that explain why it could not be applied, wrapped as `ExplainedRejection` with message `Cannot {verb}: {rejected}:\\n{report}`.","triggerScenarios":"Calling an apply/assign operation where some hunks/changes violate workspace rules (e.g. the change belongs to another branch's ownership, conflicts with an applied change, or a dependency in the workspace blocks it) and the operation is rolled back with `rejected > 0`.","commonSituations":"Trying to assign a file hunk to a branch while an overlapping hunk is already assigned elsewhere; applying a change whose path depends on unapplied workspace changes; exclusive ownership conflicts in multi-branch workspaces.","solutions":["Read the per-path report under the message — it lists each rejected change and the dependency that caused it.","Apply or reassign the blocking dependency changes first, then retry the original operation.","Resolve overlapping/conflicting assignments between branches before re-running.","If the report points to unexpected paths, refresh workspace status and retry — the rejection may be based on stale state."],"exampleFix":"// before: apply everything at once and fail\nbut.apply_all_changes()?;\n// after: inspect rejections and apply in dependency order\nmatch but.apply_all_changes() {\n    Err(e) if e.is::<ExplainedRejection>() => {\n        for path in parse_rejected_paths(&e.to_string()) {\n            assign_to_correct_branch(path)?;\n        }\n        but.apply_all_changes()?;\n    }\n    other => other?,\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn is_explained_rejection(err: &anyhow::Error) -> bool {\n    err.downcast_ref::<ExplainedRejection>().is_some()\n}","tryCatchPattern":"if let Err(e) = assign_changes(&changes) {\n    if let Some(rej) = e.downcast_ref::<ExplainedRejection>() {\n        eprintln!(\"{rej}\"); // per-path dependency report\n        return Err(e);\n    }\n    return Err(e);\n}","preventionTips":["Read the per-path report — it names the blocking dependency for every rejected change.","Keep branch assignments non-overlapping for the same paths.","Apply dependency changes before dependent ones."],"tags":["workspace","rejection","hunks","assignment"],"backgroundTag":"changes-rejected","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"}