Skip to content

[bugzillarest] Skip bug pages that return HTTP 400 instead of aborting#911

Open
aatchison wants to merge 3 commits into
chaoss:mainfrom
aatchison:upstream-skip-bugzilla-http-400
Open

[bugzillarest] Skip bug pages that return HTTP 400 instead of aborting#911
aatchison wants to merge 3 commits into
chaoss:mainfrom
aatchison:upstream-skip-bugzilla-http-400

Conversation

@aatchison

Copy link
Copy Markdown

Problem

A single bug can make the Bugzilla REST API return an HTTP 400 for a bug-list request. We hit this on bugzilla.mozilla.org, where one bug returns:

400 Bad Request — {"code":68000,"message":"Failed to fetch key <n> from network storage: Not Found"}

for GET /rest/bug?...&include_fields=_all. Because BugzillaRESTBackend.__fetch_and_parse_bugs() requests include_fields=_all and pages by last_change_time, that 400 raises out of the fetch loop and aborts the entire collection. Since the failing bug stays in the incremental window, every subsequent run fails the same way — collection is frozen indefinitely (in our case ~3 months) behind one bad bug.

Fix

Catch the HTTPError in __fetch_and_parse_bugs: on a 400, log and skip that page (advance the offset) and continue, so one bad bug no longer wedges collection. A MAX_CONSECUTIVE_SKIPS cap (reset on any success) guards against an infinite skip loop on a systemic failure and re-raises so it still surfaces. Other HTTP errors are re-raised unchanged.

The collection cursor advances normally once healthy bugs are yielded.

Tests

Added two tests (both written test-first):

  • test_fetch_skips_bug_page_on_http_400 — first page 400s; asserts the remaining bugs are still collected.
  • test_fetch_aborts_after_too_many_consecutive_400s — persistent 400s abort (bounded) rather than loop forever.

tests/test_bugzillarest.py passes (27 tests); flake8 clean. Changelog entry added under releases/unreleased/.

Arron Atchison added 2 commits June 11, 2026 09:34
A single bug can make the Bugzilla REST API return a 400 (e.g. a field
whose data is missing from network storage:
"Failed to fetch key <n> from network storage: Not Found"). Because the
backend requests include_fields=_all and pages by last_change_time, one
such bug aborts the whole batch and freezes incremental collection
indefinitely.

Catch the HTTPError in __fetch_and_parse_bugs: on a 400, log and skip
that page (advance the offset) and continue, so one bad bug no longer
wedges collection. A MAX_CONSECUTIVE_SKIPS cap (reset on any success)
guards against an infinite skip loop on a systemic failure, re-raising
so it still surfaces.

Adds tests for both behaviours (skip-and-continue, and abort-after-cap).

(cherry picked from commit e85b333cab00f1072f0bcdb80a2d9271d8f3c123)
Signed-off-by: Arron Atchison <aatchison@thunderbird.net>
Signed-off-by: Arron Atchison <aatchison@thunderbird.net>
@aatchison aatchison force-pushed the upstream-skip-bugzilla-http-400 branch from aa551e5 to 1a416b4 Compare June 11, 2026 16:34
@aatchison aatchison marked this pull request as draft June 11, 2026 17:30
With include_fields=_all, a large batch can return a response too big to be
parsed (truncated JSON), which previously aborted the whole collection. On a
JSONDecodeError the backend now halves the batch and retries; if a single bug
is still unparseable at a batch size of one, it is skipped. The existing
consecutive-skip cap also bounds this path.

Broadens the changelog entry to cover both the HTTP 400 skip and the
unparseable-response recovery.

Signed-off-by: Arron Atchison <aatchison@thunderbird.net>
@aatchison aatchison marked this pull request as ready for review June 11, 2026 19:30
@aatchison

Copy link
Copy Markdown
Author

Follow-up: #912 adds transient-5xx recovery (reduce batch + retry), stacked on this PR. Please review/merge this one first.

@jjmerchante jjmerchante left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your proposal. Please see my comments below.

raise
logger.warning("Skipping bugs page at offset %s after HTTP 400: %s",
offset, e.response.text)
offset += batch

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On an HTTP 400, offset += batch permanently skips an entire page, so up to ~499 perfectly good bugs in that window are silently dropped and never retried.

What about handling this similarly to JSONDecodeError by halving the batch size until the problematic bug is identified, and then continuing the collection?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants