Skip to content

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
mainfrom
shoumikhin/linkcheck-fewer-false-positives
Open

Fix the nightly link check: stop failing on no-response, repair every dead link it found#21694
shoumikhin wants to merge 1 commit into
mainfrom
shoumikhin/linkcheck-fewer-false-positives

Conversation

@shoumikhin

@shoumikhin shoumikhin commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

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

000 is treated as a dead link

scripts/lint_urls.sh asks curl for an HTTP status code and fails the URL when the code is below 200 or 400 and above. When curl cannot reach the server at all it does not get an HTTP code, so it reports 000.

000 means 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 000 URLs changes from night to night, while the set of 404s stays exactly the same.

Fix: treat 000 the way the script already treats 403, 429 and 503. Print WARN and 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 into jq, which prints jq: parse error into 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 WARN either way. This also removes up to 30 seconds of sleeping per unreachable URL, and the jq dependency 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/stargazers behaves the same way, so this is not something about this repo.

Fix: mark it with the @lint-ignore marker the script already supports. The
marker 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.py builds a download URL out of two
string 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 the
server for it. That is a path prefix, not a page. The server answered 301 in
the most recent nightly and 404 an hour later, so this line can turn the job
red 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-ignore too.

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.sh downloads a photo to feed to the model:

curl -o basketball.jpg https://upload.wikimedia.org/wikipedia/commons/7/73/Chicago_Bulls_and_New_Jersey_Nets%2C_March_28%2C_1991.jpg

That file was renamed on Wikimedia Commons, so the URL now returns 404. Without -f, curl still exits 0 and writes the error body to disk, so basketball.jpg becomes a 124 byte text file. The script's own guard is if [[ ! -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:

$ curl -o basketball.jpg <old url> ; echo $?
0
$ file basketball.jpg
basketball.jpg: ASCII text, with no line terminators     (124 bytes)

$ curl -fL -o basketball.jpg <new url> ; echo $?
0
$ file basketball.jpg
basketball.jpg: JPEG image data, 974x696                 (242775 bytes)

Fix: point at the current name, and add -fL so that a future rename fails the job loudly instead of silently. The script runs under set -e, so a non-zero curl stops it right there.

Five links that no longer resolve

  • .ci/docker/common/install_openssl.sh pointed 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.md pointed at pytorch.org/cppdocs/library.html, which the C++ docs site no longer publishes. It now points at the Torch Library API page, which is where TORCH_LIBRARY is documented today.
  • test/models/export_program.py had a comment citing pytorch.org/cppdocs/notes/tensor_indexing.html. The whole notes section 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.md linked 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.py cites a Qwen issue comment that explains why a vocab size mismatch is acceptable. The repository was renamed from QwenLM/Qwen2.5 to QwenLM/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.

  • Before: 9 FAIL, 22 WARN, 2117 OK.
  • After the first round of fixes: 1 FAIL, 36 WARN, 2106 OK.
  • After the second round: 0 FAIL, 33 WARN, 2110 OK. 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:

  • The Qualcomm path prefix, which the nightly had reported as OK 301 an hour
    earlier. It is now marked with @lint-ignore.
  • The Qwen issue link, which is a genuine rename described above.

Every remaining WARN is a 403 from a site that blocks non-browser clients,
such as cppreference, Stack Overflow, Cadence and vulkan.org, plus two 000
timeouts. None of them hides a 404.

Also checked separately:

  • Ran the patched script over a small test repository containing a hostname that
    does not exist. It prints WARN 000 and exits 0. The version on main prints
    FAIL 000 and exits 1, and its check-host.net call also fails in the same run.
  • Extracted the URLs from every changed file using the script's own regular
    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.
  • Confirmed the replacement C++ docs page is the right one. It is titled Torch
    Library API and contains the TORCH_LIBRARY usage example. It has no anchor
    matching the old deep link, so the page itself is the closest target.
  • Downloaded both the old and the new image URL, as shown above.

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.

Copilot AI lite review requested due to automatic review settings August 8, 2026 23:03
@pytorch-bot

pytorch-bot Bot commented Aug 8, 2026

Copy link
Copy Markdown

🔗 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 Failures

As of commit 70e4370 with merge base fb5eedc (image):

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.

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Aug 8, 2026
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown

This PR needs a release notes: label

If your change should be included in the release notes (i.e. would users of this library care about this change?), please use a label starting with release notes:. This helps us keep track and include your important work in the next release notes.

To add a label, you can comment to pytorchbot, for example
@pytorchbot label "release notes: none"

For more information, see
https://github.com/pytorch/pytorch/wiki/PyTorch-AutoLabel-Bot#why-categorize-for-release-notes-and-how-does-it-work.

@shoumikhin
shoumikhin force-pushed the shoumikhin/linkcheck-fewer-false-positives branch from dbb9910 to 091bebf Compare August 8, 2026 23:33
Copilot AI review requested due to automatic review settings August 8, 2026 23:33

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@shoumikhin
shoumikhin force-pushed the shoumikhin/linkcheck-fewer-false-positives branch from 091bebf to 8ca5333 Compare August 9, 2026 04:39
Copilot AI review requested due to automatic review settings August 9, 2026 04:39

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@shoumikhin shoumikhin changed the title Make the nightly link check trustworthy: stop failing on no-response, fix the one real dead link Fix the nightly link check: stop failing on no-response, repair every dead link it found Aug 9, 2026
@shoumikhin
shoumikhin force-pushed the shoumikhin/linkcheck-fewer-false-positives branch from 8ca5333 to 6813118 Compare August 9, 2026 04:51
Copilot AI review requested due to automatic review settings August 9, 2026 04:51
@shoumikhin
shoumikhin requested a review from psiddh as a code owner August 9, 2026 04:51

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI review requested due to automatic review settings August 9, 2026 05:41
@shoumikhin
shoumikhin force-pushed the shoumikhin/linkcheck-fewer-false-positives branch from 6813118 to a6bb414 Compare August 9, 2026 05:41

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@shoumikhin
shoumikhin force-pushed the shoumikhin/linkcheck-fewer-false-positives branch from a6bb414 to 6c4e82c Compare August 9, 2026 05:55
Copilot AI review requested due to automatic review settings August 9, 2026 05:55

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI review requested due to automatic review settings August 10, 2026 05:51
@shoumikhin
shoumikhin force-pushed the shoumikhin/linkcheck-fewer-false-positives branch from 6c4e82c to 70e4370 Compare August 10, 2026 05:51

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants