gitbutlerapp/gitbutler · error · anyhow::Error
Stopped listing GitLab merge requests after unsafe paginatio
Error message
Stopped listing GitLab merge requests after unsafe pagination state
What it means
list_merge_requests follows GitLab's x-next-page header page by page (per_page=100). Before each request it validates the page number: it must parse as a positive integer, must not have been visited already, and the total number of fetched pages must stay under 10,000 (MAX_MERGE_REQUEST_REQUESTS). When the server's pagination headers violate these rules - typically by replaying the same next page forever - the loop would never terminate, so the client stops and fails instead.
Source
Thrown at crates/but-gitlab/src/client.rs:198
);
self.list_merge_requests(&url, &[], "Failed to list merge requests for commit")
.await
}
async fn list_merge_requests(
&self,
url: &str,
query: &[(&str, &str)],
error_message: &str,
) -> Result<Vec<MergeRequest>> {
let mut mrs = Vec::new();
let mut next_page = Some("1".to_string());
let mut seen_pages = HashSet::new();
while let Some(page) = next_page.take() {
if !merge_request_page_is_safe(&page, &mut seen_pages) {
bail!("Stopped listing GitLab merge requests after unsafe pagination state");
}
let response = self
.client
.get(url)
.query(query)
.query(&[("per_page", "100"), ("page", page.as_str())])
.send()
.await?;
if !response.status().is_success() {
bail!("{error_message}: {}", response.status());
}
next_page = next_page_from_headers(response.headers());
let mut page_mrs: Vec<GitLabMergeRequest> = response.json().await?;
if page_mrs.is_empty() {
break;
}View on GitHub (pinned to caf1f223d3)
Solutions
- Retry the operation - header anomalies are often transient
- If reproducible, capture the x-next-page headers (curl -I) and check the GitLab version and any proxy configuration
- Narrow the listing with filters (state, assignee, updated_after) to reduce the page count
Defensive patterns
Strategy: retry
Try / catch
let mrs = match client.list_merge_requests(...).await {
Err(e) if e.to_string().contains("unsafe pagination state") => {
tokio::time::sleep(Duration::from_secs(5)).await;
client.list_merge_requests(...).await? // one retry: header glitches are usually transient
}
other => other?,
}; Prevention
- Add filters (state, assignee, updated_after) so listings fit few pages
- Keep GitLab patched - pagination header bugs are version-specific
- Check proxies for header mangling when this repeats
When it happens
Trigger: A GitLab instance or a proxy in front of it returns a duplicate x-next-page value so the same page repeats; a non-numeric or zero next-page header; a listing so vast it would exceed 10,000 pages of 100 merge requests.
Common situations: Self-managed GitLab versions with pagination bugs; reverse proxies that mangle response headers; extremely large projects.
Related errors
- Stopped listing GitLab jobs for pipeline {} after unsafe pag
- Failed to list jobs for pipeline: {}
- Bitbucket pagination exceeded the {MAX_PAGES}-page safety ca
- Bitbucket request failed: {}
- Could not restore native GitHub stack membership after the p
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/7088f6762f7d2c71.
Report an issue: GitHub.