Fix the nightly link check: stop failing on no-response, repair every dead link it found - #21694
Open
shoumikhin wants to merge 1 commit into
Open
Fix the nightly link check: stop failing on no-response, repair every dead link it found#21694shoumikhin wants to merge 1 commit into
shoumikhin wants to merge 1 commit into
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/21694
Note: Links to docs will display an error until the docs builds have been completed. ❌ 1 Cancelled Job, 4 Unrelated Failures, 2 Unclassified FailuresAs of commit 70e4370 with merge base fb5eedc ( UNCLASSIFIED FAILURES - DrCI could not classify the following jobs because the workflow did not run on the merge base. The failures may be pre-existing on trunk or introduced by this PR:
CANCELLED JOB - The following job was cancelled. Please retry:
FLAKY - The following jobs failed but were likely due to flakiness present on trunk:
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
This PR needs a
|
shoumikhin
force-pushed
the
shoumikhin/linkcheck-fewer-false-positives
branch
from
August 8, 2026 23:33
dbb9910 to
091bebf
Compare
shoumikhin
force-pushed
the
shoumikhin/linkcheck-fewer-false-positives
branch
from
August 9, 2026 04:39
091bebf to
8ca5333
Compare
shoumikhin
requested review from
kirklandsign,
larryliu0820 and
mergennachin
as code owners
August 9, 2026 04:39
shoumikhin
force-pushed
the
shoumikhin/linkcheck-fewer-false-positives
branch
from
August 9, 2026 04:51
8ca5333 to
6813118
Compare
shoumikhin
force-pushed
the
shoumikhin/linkcheck-fewer-false-positives
branch
from
August 9, 2026 05:41
6813118 to
a6bb414
Compare
shoumikhin
force-pushed
the
shoumikhin/linkcheck-fewer-false-positives
branch
from
August 9, 2026 05:55
a6bb414 to
6c4e82c
Compare
… dead link it found
shoumikhin
force-pushed
the
shoumikhin/linkcheck-fewer-false-positives
branch
from
August 10, 2026 05:51
6c4e82c to
70e4370
Compare
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.
What is broken
The nightly link check has been red for many nights in a row. Most of what it reports is not a real problem, so nobody reads it any more. Hiding behind that noise were four genuinely dead links, one of which quietly breaks a CI test.
The most recent nightly reported 9 failing URLs. This change clears all 9.
Part 1: the checker reports failures that are not failures
000is treated as a dead linkscripts/lint_urls.shaskscurlfor an HTTP status code and fails the URL when the code is below 200 or 400 and above. Whencurlcannot reach the server at all it does not get an HTTP code, so it reports000.000means DNS failed, or the TLS handshake failed, or the connection was reset, or the request timed out. On a CI runner making hundreds of requests to hundreds of hosts in parallel that happens constantly, and it says nothing about whether the link is dead. Two of the 9 failures were this.Good evidence that these are noise: the set of
000URLs changes from night to night, while the set of 404s stays exactly the same.Fix: treat
000the way the script already treats403,429and503. PrintWARNand keep going.The third party fallback made it worse
When both direct attempts failed, the script asked
check-host.net, a free outside service, to fetch the URL instead. That service rate limits us, so it usually answers with an error page rather than JSON. The script pipes that answer intojq, which printsjq: parse errorinto the log.Fix: delete the fallback. It can no longer change any outcome, because a URL the server really answered for already has its code from the first two attempts, and a URL nothing answered for is now a
WARNeither way. This also removes up to 30 seconds of sleeping per unreachable URL, and thejqdependency with it.GitHub hides some pages from non-browser clients
The README star badge links to
https://github.com/pytorch/executorch/stargazers. That page is fine in a browser, but GitHub answers 404 to any client that is not one.github.com/pytorch/pytorch/stargazersbehaves the same way, so this is not something about this repo.Fix: mark it with the
@lint-ignoremarker the script already supports. Themarker only suppresses URLs that start before it on the same line, and that line
also carries the badge image URL, so the marker goes between the link and the
image. That way the star link is skipped and the badge image is still checked.
Half of a URL is not a page
backends/qualcomm/scripts/download_qnn_sdk.pybuilds a download URL out of twostring pieces so that the SDK version can be inserted in the middle. The checker
reads one line at a time, so it sees only the first piece,
https://softwarecenter.qualcomm.com/api/download/software/sdks/, and asks theserver for it. That is a path prefix, not a page. The server answered
301inthe most recent nightly and
404an hour later, so this line can turn the jobred at any moment for no reason. The assembled URL is checked separately from
the Qualcomm backend documentation page and answers 206.
Fix: mark that line with
@lint-ignoretoo.Part 2: the links that really are dead
A CI test has been downloading an error page instead of an image
.ci/scripts/test_llava.shdownloads a photo to feed to the model:That file was renamed on Wikimedia Commons, so the URL now returns 404. Without
-f,curlstill exits 0 and writes the error body to disk, sobasketball.jpgbecomes a 124 byte text file. The script's own guard isif [[ ! -f "basketball.jpg" ]], and the file does exist, so nothing complains. The test then runs on something that is not an image.Running both commands today:
Fix: point at the current name, and add
-fLso that a future rename fails the job loudly instead of silently. The script runs underset -e, so a non-zerocurlstops it right there.Five links that no longer resolve
.ci/docker/common/install_openssl.shpointed at the file it was copied from in PyTorch core. Core deleted its copy in pytorch/pytorch pull request 179513. It now points at the last revision that still has the file, so it cannot rot again.docs/source/kernel-library-custom-aten-kernel.mdpointed atpytorch.org/cppdocs/library.html, which the C++ docs site no longer publishes. It now points at the Torch Library API page, which is whereTORCH_LIBRARYis documented today.test/models/export_program.pyhad a comment citingpytorch.org/cppdocs/notes/tensor_indexing.html. The wholenotessection is gone from that site and there is no replacement page, so the comment now names the source in words instead of linking to it.docs/source/success-stories.mdlinked to an iOS app that is no longer listed on the App Store. Apple's lookup service returns no result for that app id in any storefront. The other two links in that entry still work and are unchanged.examples/models/llama/runner/generation.pycites a Qwen issue comment that explains why a vocab size mismatch is acceptable. The repository was renamed fromQwenLM/Qwen2.5toQwenLM/Qwen3. GitHub's rename redirect works for the repository root but not for the issue path, which returns 404. The comment is still there under the new name, so the link now points at it.How this was verified
The real test: the link check job was run over the whole tree, in the same
whole-repository mode the nightly uses, with every change in this PR applied.
FAIL, 22WARN, 2117OK.FAIL, 36WARN, 2106OK.FAIL, 33WARN, 2110OK. The job passes.All 9 original failures are gone. Two further URLs turned up along the way, each
one a different problem that the nightly had not reported, and each was fixed in
turn:
OK 301an hourearlier. It is now marked with
@lint-ignore.Every remaining
WARNis a403from a site that blocks non-browser clients,such as cppreference, Stack Overflow, Cadence and vulkan.org, plus two
000timeouts. None of them hides a 404.
Also checked separately:
does not exist. It prints
WARN 000and exits 0. The version on main printsFAIL 000and exits 1, and itscheck-host.netcall also fails in the same run.expression, and confirmed that none of the 9 failing URLs is still there and
that every URL that remains answers 200. That same check is what showed the
marker placement matters: with the marker at the end of the README line, the
badge image URL was skipped too.
Library API and contains the
TORCH_LIBRARYusage example. It has no anchormatching the old deep link, so the page itself is the closest target.
What this means going forward
A URL now fails the job only when a server actually answered and said the page is gone. A URL that could not be reached shows up as
WARN, stays visible in the log, and does not turn the job red. With the tree clean, a red nightly link check means something again.