Repository navigation
A Mercor 5xx is content not obtained: exit 5, or 6 after rows, never 4 - #8
Merged
Merged
Conversation
A page the site answered with a server error was classified unknown, retried, and then counted as served with no rows. A run whose only page was a 503 therefore reported an empty result (exit 4). Each engine (Playwright, Selenium, pyppeteer) still retries the page within its existing budget. When every attempt is a 5xx, the page is now marked failed with its status, so the run stops with target_http_5xx: exit 5 on page 1, exit 6 after earlier rows. The sidecar records the status per page in pages_target_http_error. With no rows nothing is written, so earlier output and its sidecar are kept. scraper_api_client.py applies the same rule to http_code, retrying within --retries. A Scraper API status 'error' with no target status is exit 5. A 404 is still exit 4. Co-Authored-By: Claude Opus 5.5 <[email protected]>
jehrr
marked this pull request as ready for review
October 15, 2026 23:50
This was referenced Oct 16, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When Mercor answered with a server error,
detect_page_stateclassified the pageunknown. The engines retried it and then counted it as a served page with no rows. As a result, a run whose only page was a 503 reported an empty result (exit 4), and a 502 inside a--mode jobqueue was skipped while the run still saidcomplete. The same happened throughscraper_api_client.py, where the target's status ishttp_codeof an HTTP 200 Scraper API answer. That path also made only one attempt.A 5xx says nothing about what the page holds. The requested content was not obtained.
Resulting behaviour
The same rule now applies in Playwright, Selenium, pyppeteer and the Scraper API client:
--retriesin the client). A 5xx that clears on a retry is a normal run.target_http_5xx. The run exits 5 if this happens on page 1 and 6 after earlier rows. It never exits 4.pages_target_http_error(for example{"1": 503}). The sidecar is written asfailedunder--allow-empty, and aspartialwhen rows exist.status: "error"with no target status: exit 5.not_found).target_server_error,failure_stop_reasonandtarget_http_errorslive inpage_flow.py. They replace seven copies of the inline stop-reason expression.[Unreleased].Evidence
check_a_target_5xx_is_content_not_obtained_in_every_engineruns each engine's realscrape()and_fetch_one_page, with only the browser primitives stubbed (goto /driver.get+_document_status/ pyppeteergoto). It asserts:1 + BLOCK_RETRIES_WITHOUT_POOL;o.jsonando.meta.jsonare byte-identical after the failed run;--allow-emptythe sidecar saysfailed,target_http_5xx,pages_failed [1],{"1": 503};partial,{"2": 502};check_a_target_5xx_is_content_not_obtained_in_the_scraper_api_clientruns the real client withrequests.poststubbed. It asserts:http_code: 503is exit 5 after 2 attempts, and nothing is written;--allow-emptythe sidecar is written asfailedwith the status;status: "error"with nohttp_codeis exit 5.The pre-change code fails both checks: a 503 gave exit 4, and the client made 1 attempt.
Planted-fault controls. Each was run in its engine's venv with
PYTHONDONTWRITEBYTECODE=1and caches cleared, went red on the named assertions, and was green after restore:pages_target_http_error;okignoresserver_error;failure_stop_reasonloses the 5xx case;status: "error".One more planted fault, sweeping 4xx into the 5xx rule, stayed green. That fault cannot be reached: a 404 is classified
not_foundbeforeunknown, and the 404 assertions cover it.Suites:
ci_checks.py --help-check --sample-check --secret-checkpasses.No live, paid or credentialled calls were made.
Not changed
unknownwithout a 5xx) is out of scope; that path is not a target 5xx.🤖 Generated with Claude Code