{"record":{"id":"694dbea045e4a9ab","repo":"gitbutlerapp/gitbutler","slug":"assignments-error-assignments-error-map-err-serde-error","errorCode":null,"errorMessage":"assignments_error: assignments_error.map(|err| serde_error::Error::new(&*err))","messagePattern":"assignments_error: assignments_error\\.map\\(\\|err\\| serde_error::Error::new\\(&\\*err\\)\\)","errorType":"error_code","errorClass":"serde_error::Error","httpStatus":null,"severity":"warning","filePath":"crates/but-api/src/diff.rs","lineNumber":233,"sourceCode":"            trans.hunk_assignments_mut()?,\n            &repo,\n            &ws,\n            Some(changes.changes.clone()),\n            context_lines,\n        )?\n    };\n\n    trans.commit()?;\n\n    let mut worktree_changes: but_core::ui::WorktreeChanges = changes.into();\n    worktree_changes.modification_times =\n        but_core::diff::ui::modification_times(&repo, &worktree_changes);\n    drop((repo, ws, db));\n\n    Ok(WorktreeChanges {\n        worktree_changes,\n        assignments,\n        assignments_error: assignments_error.map(|err| serde_error::Error::new(&*err)),\n        dependencies: dependencies.as_ref().ok().cloned(),\n        dependencies_error: dependencies\n            .as_ref()\n            .err()\n            .map(|err| serde_error::Error::new(&**err)),\n    })\n}\n\n/// Persists `assignments` for the current workspace without creating an oplog\n/// entry.\n///\n/// This acquires shared worktree access from `ctx` before writing\n/// assignments.\n///\n/// See [`assign_hunk_only_with_perm()`] for details.\n#[but_api]\n#[instrument(skip_all, err(Debug))]\npub fn assign_hunk_only(","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-api/src/diff.rs#L215-L251","documentation":"Not a thrown error but an error field on the WorktreeChanges result: assignments_error carries the failure that occurred while computing workspace assignments, serialized via serde_error::Error for the client. The main worktree_changes payload is still returned; this signals the assignments portion is missing.","triggerScenarios":"The workspace assignment computation inside the worktree-changes API fails (workspace/database lookup error) while diffing succeeds — the Result::Err is captured and attached rather than propagated.","commonSituations":"Corrupt or stale workspace data, a failed workspace snapshot read, or concurrent modification of the workspace during the call.","solutions":["Inspect the serialized assignments_error message for the root cause","Re-open/refresh the workspace state and retry the worktree-changes call","Treat the result as partial: use worktree_changes but regenerate assignments separately","If persistent, reset/rebuild workspace metadata via the workspace APIs"],"exampleFix":"// before\nconst wc = await api.worktreeChanges(...); use(wc.assignments);  // may be null\n// after\nconst wc = await api.worktreeChanges(...);\nif (wc.assignmentsError) console.warn(wc.assignmentsError);\nuse(wc.assignments ?? []);","handlingStrategy":"fallback","validationCode":null,"typeGuard":"const hasAssignments = (wc) => wc.assignmentsError == null && Array.isArray(wc.assignments);","tryCatchPattern":"const wc = await api.worktreeChanges(...);\nif (wc.assignmentsError) { log.warn('assignments unavailable:', wc.assignmentsError); }\nconst assignments = wc.assignments ?? [];","preventionTips":["Never assume assignments is non-null on WorktreeChanges","Always surface assignments_error to the UI as a degraded state","Retry the call after workspace metadata changes"],"tags":["workspace","assignments","partial-failure"],"backgroundTag":"internal-invariant-violation","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"}