ax-check rule

AXC-F001: Claimed URL is broken

A URL in the file returned 404 or 410, or its host did not resolve.

ax-check is a checker being prepared for release. This page documents the rule ahead of that release; see all 50 rules.

Severityerror
KindObserved. Depends on the program and environment at run time.
Modeax-check drift
Applies toInstruction files and manifests
Pattern tagsdrift, docs-for-agents, llms-txt
Fix in one lineUpdate or remove the link, or restore the page and redirect the old address.

A URL written in the file answered with 404 or 410, or its host name did not resolve. The file tells an agent to read a page that is no longer there. The agent either fails, or guesses and carries on with less than it needs.

What it checks

ax-check collects every http:// and https:// URL in the file. It sends a HEAD request first and falls back to GET if the server does not answer HEAD well. This rule fires when the answer is 404 (not found), 410 (gone) or when the host name does not resolve in DNS.

Other failures, such as access denied, rate limiting, server errors or timeouts, are not reported here. They are reported as AXC-F002, because they do not prove the page is gone.

Why it matters

Files such as llms.txt exist so that a language model can find a curated list of links (llms.txt proposal). Agent instruction files such as AGENTS.md and SKILL.md work the same way: they point the agent at the pages that explain how to do the work. A dead link silently removes that help. Links go stale as sites are reorganised, and nobody reads the file often enough to notice.

How to fix

  • Update the link to the page’s new address.
  • If the page moved, restore the old address and redirect it to the new one, so other readers of the old link are not stranded.
  • If the page is gone for good, remove the link and the sentence that depends on it.

Example

Find it:

ax-check drift --online llms.txt

Before

# Invoice Kit

> Billing tools for small teams.

## Docs

- [Quick start](https://docs.invoicekit.dev/quick-start): install and first invoice
- [Webhook guide](https://docs.invoicekit.dev/webhooks-v1): events and retries

The webhook guide was renamed, and the old address now returns 404.

After

# Invoice Kit

> Billing tools for small teams.

## Docs

- [Quick start](https://docs.invoicekit.dev/quick-start): install and first invoice
- [Webhook guide](https://docs.invoicekit.dev/webhooks): events and retries

How ax-check detects it

The extraction and the rule logic are deterministic, but the result depends on what the servers that host each URL answer at the time of the run, so the same file can give different findings on another day. JSON and SARIF reports record when and where the check ran. It extracts URLs with a simple pattern, trims trailing punctuation that belongs to the sentence, and requests each distinct URL once. Redirects are followed. It sends HEAD first. Some servers handle HEAD badly, so if the answer is 403, 404, 405, 501 or any 5xx status, ax-check repeats the request as GET before it judges. The final status decides:

  • 404 or 410: this rule fires.
  • A host name that does not resolve in DNS: this rule fires.
  • Success or a redirect (status 200 to 399): no finding.
  • Anything else, including a timeout: AXC-F002, because it does not prove the page is gone.

It makes one request at a time per host, leaves a gap of 500 milliseconds between requests to the same host, waits at most 10 seconds for each (change it with --timeout <ms>), and checks at most 200 distinct URLs per run (change it with --max-urls <n>). URLs beyond the cap are reported as AXC-F002, not skipped silently.

It deliberately skips URLs that cannot be checked in a useful way: localhost, loopback addresses (127.*, ::1), 0.0.0.0, the reserved example domains (example.com, example.org, example.net, .example, .test, .invalid, .local), host names with no dot (such as https://host/mcp, a common placeholder), addresses that contain { or < placeholders, and addresses written directly before a placeholder (such as https://example.org/checks/<rule-id>/).

Known limits:

  • A page that returns 200 but shows an error message in its body is not detected.
  • A DNS failure that is only temporary is reported as a broken host. Run the check again.

To see which URLs would be requested before any request is made, run ax-check drift --online --dry-run llms.txt. Without --online, this rule does not run. Offline mode reports the number of unverified URLs once per file under AXC-F011.

To silence it, run ax-check drift --online --disable AXC-F001 llms.txt. Only do that when the finding does not apply, for example a link you know is served only to signed-in users.

Sources

Records in the AX evidence register that share a pattern tag with this rule. A shared tag means the record is about the same pattern, not that it tests this rule. Read the evidence class before the number.