{"record":{"id":"3c147a42f092cb7d","repo":"gitbutlerapp/gitbutler","slug":"error-error-response-status-error-message","errorCode":null,"errorMessage":"Error ${error.response.status}: ${error.message}","messagePattern":"Error (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/web/src/lib/owner/ownerService.ts","lineNumber":106,"sourceCode":"\t\t\t\t};\n\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"user\",\n\t\t\t\t\tdata: user,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// If owner_type is not set or unknown, return not found\n\t\t\treturn { type: \"not_found\" };\n\t\t} catch (error: any) {\n\t\t\tif (error.response) {\n\t\t\t\t// Return not_found for 404s\n\t\t\t\tif (error.response.status === 404) {\n\t\t\t\t\treturn { type: \"not_found\" };\n\t\t\t\t}\n\n\t\t\t\t// For all other error status codes, throw the error\n\t\t\t\tthrow new Error(`Error ${error.response.status}: ${error.message}`);\n\t\t\t}\n\n\t\t\t// For network errors or other non-HTTP errors\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n","sourceCodeStart":88,"sourceCodeEnd":114,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/apps/web/src/lib/owner/ownerService.ts#L88-L114","documentation":"During upstream integration validation, each stack collects the BottomUpdates that touch its bottoms. If any of them uses BottomUpdateKind::Merge and more than one relevant update exists for that stack, the code bails: merge-based integration is only defined for a single update per stack, since two merges cannot be composed unambiguously.","triggerScenarios":"Passing an updates Vec to integrate_upstream where two or more BottomUpdate entries with kind Merge have selectors whose shas are contained in the same stack.bottoms set.","commonSituations":"Batching several workspace updates where two merged upstreams both land at bottoms of one stack; programmatically generating one merge update per upstream branch and applying them in one call; UI selecting multiple merge updates simultaneously.","solutions":["Apply merge updates one at a time: call integrate_upstream with a single Merge BottomUpdate per invocation","Convert all but one of the updates to the rebase kind (BottomUpdateKind::Rebase) so the rebase path composes them","Re-check which selectors map into each stack's bottoms and split the call so each stack sees at most one merge"],"exampleFix":"// before\nlet updates = vec![merge_update_a, merge_update_b]; // both Merge, same stack\nintegrate_upstream(..., updates, ...)?;\n\n// after\nintegrate_upstream(..., vec![merge_update_a], ...)?;\nintegrate_upstream(..., vec![merge_update_b], ...)?;","handlingStrategy":"validation","validationCode":"// at most one Merge update per stack before calling integrate_upstream\nfor stack in &stacks {\n    let merges: Vec<_> = updates.iter().filter(|u| u.kind == BottomUpdateKind::Merge\n        && stack.bottoms.contains(&u.selector)).collect();\n    assert!(merges.len() <= 1, \"stack has {} merge updates; apply them one by one\", merges.len());\n}","typeGuard":null,"tryCatchPattern":"match integrate_upstream(...) {\n    Err(err) if err.to_string().contains(\"multiple updates for a stack\") => {\n        // split the batch: one merge update per call, retry\n    }\n    other => other.map(|_| ()),\n}","preventionTips":["Apply merge-kind updates one per invocation","Derive updates from the current graph projection so selector-to-stack mapping is accurate"],"tags":["rust","git","gitbutler","merge","stacks","upstream-integration"],"backgroundTag":"conflicting-merge-updates","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-23T21:17:23.414Z"}