gitbutlerapp/gitbutler · error · Error

Error ${error.response.status}: ${error.message}

Error message

Error ${error.response.status}: ${error.message}

What it means

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.

Source

Thrown at apps/web/src/lib/owner/ownerService.ts:106

				};

				return {
					type: "user",
					data: user,
				};
			}

			// If owner_type is not set or unknown, return not found
			return { type: "not_found" };
		} catch (error: any) {
			if (error.response) {
				// Return not_found for 404s
				if (error.response.status === 404) {
					return { type: "not_found" };
				}

				// For all other error status codes, throw the error
				throw new Error(`Error ${error.response.status}: ${error.message}`);
			}

			// For network errors or other non-HTTP errors
			throw error;
		}
	}
}

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Apply merge updates one at a time: call integrate_upstream with a single Merge BottomUpdate per invocation
  2. Convert all but one of the updates to the rebase kind (BottomUpdateKind::Rebase) so the rebase path composes them
  3. Re-check which selectors map into each stack's bottoms and split the call so each stack sees at most one merge

Example fix

// before
let updates = vec![merge_update_a, merge_update_b]; // both Merge, same stack
integrate_upstream(..., updates, ...)?;

// after
integrate_upstream(..., vec![merge_update_a], ...)?;
integrate_upstream(..., vec![merge_update_b], ...)?;
Defensive patterns

Strategy: validation

Validate before calling

// at most one Merge update per stack before calling integrate_upstream
for stack in &stacks {
    let merges: Vec<_> = updates.iter().filter(|u| u.kind == BottomUpdateKind::Merge
        && stack.bottoms.contains(&u.selector)).collect();
    assert!(merges.len() <= 1, "stack has {} merge updates; apply them one by one", merges.len());
}

Try / catch

match integrate_upstream(...) {
    Err(err) if err.to_string().contains("multiple updates for a stack") => {
        // split the batch: one merge update per call, retry
    }
    other => other.map(|_| ()),
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/3c147a42f092cb7d. Report an issue: GitHub.