gitbutlerapp/gitbutler · info · serde_error::Error

assignments_error: assignments_error.clone()…

Error message

assignments_error: assignments_error.clone() (dependencies_error: serde_error::Error::new(&**err))

What it means

When the file watcher emits `WorktreeChanges`, hunk-assignment failures cannot be serialized as the original anyhow error chain, so `dependencies_error` (and analogously `assignments_error`) is converted via `serde_error::Error::new`. This preserves the top-level message for the UI while making the error serializable across the app-event boundary.

Solutions

  1. Read the message in `dependencies_error`/`assignments_error` on the emitted `Change::WorktreeChanges` event to see the root cause.
  2. Wait for the next watcher tick — transient git states resolve themselves once operations finish.
  3. Resolve merge conflicts or complete in-progress operations in the repository.
  4. If persistent, re-open the project to rebuild watcher state.
Defensive patterns

Strategy: try-catch

Try / catch

on_change(|change: Change| match change {
    Change::WorktreeChanges { changes, .. } if changes.dependencies_error.is_some() => {
        warn("dependency computation failed; waiting for next tick");
    }
    _ => {}
})

Prevention

When it happens

Trigger: A watcher tick computes worktree changes; the dependency computation inside `but_hunk_assignment::WorktreeChanges` fails (e.g. target resolution or file dependency analysis error), producing `dependencies_error` on the emitted event.

Common situations: Repository in a transient state during a rebase/checkout while the watcher fires; unresolved merge conflicts breaking dependency analysis; large or binary files failing dependency computation; git object access errors mid-scan.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/3b608df715e6efcf. Report an issue: GitHub.

Appendix: source

Thrown at crates/gitbutler-watcher/src/handler.rs:134

            &repo,
            &ws,
            wt_changes.changes.clone(),
            context_lines,
        )?;

        let mut worktree_changes: but_core::ui::WorktreeChanges = wt_changes.clone().into();
        worktree_changes.modification_times =
            but_core::diff::ui::modification_times(&repo, &worktree_changes);

        let changes = but_hunk_assignment::WorktreeChanges {
            worktree_changes,
            assignments: assignments.clone(),
            assignments_error: assignments_error.clone(),
            dependencies: dependencies.as_ref().ok().cloned(),
            dependencies_error: dependencies
                .as_ref()
                .err()
                .map(|err| serde_error::Error::new(&**err)),
        };
        let _ = self.emit_app_event(Change::WorktreeChanges {
            project_id,
            changes,
            changed_paths: Arc::from(paths),
        });
        Ok(())
    }

    pub fn git_files_change(
        &self,
        project_id: ProjectHandleOrLegacyProjectId,
        paths: Vec<PathBuf>,
        ctx: &mut Context,
        perm: &mut RepoExclusive,
    ) -> Result<()> {
        let (head_ref_name, head_sha) = head_info(ctx)?;
        let mut saw_workspace_activity = false;

View on GitHub (pinned to 58e5313667)