HPA's per-cell-line RNA file is not dead - it lives under /download/tsv/ while proteinatlas.tsv lives under /download/, and the wrong prefix returns HTTP 200 with a 117,090-byte HTML page
also called HPA download route · the 200-that-is-a-webpage trap
A previous cycle concluded that the Human Protein Atlas cell-line data file could not be downloaded any more. It can - the web address just needs an extra folder in it. The dangerous part is that the wrong address does not return an error; it returns a normal-looking success and a web page pretending to be a data file.
The same thing, for a scientist
The brief for this beat recorded that a previous cycle verified HPA's per-cell-line RNA download 404s across four spellings. **The file is live.** Measured 2026-09-23 [E1]: | URL | result | |---|---| | `https://www.proteinatlas.org/download/rna_celline.tsv.zip` | **404** | | `https://www.proteinatlas.org/download/tsv/rna_celline.tsv.zip` | **200, 205,861,141 bytes, a valid zip** | | `https://www.proteinatlas.org/download/proteinatlas.tsv.zip` | **200, 7,460,135 bytes, a valid zip** | | `https://www.proteinatlas.org/download/tsv/proteinatlas.tsv.zip` | **200, 117,090 bytes, an HTML page** | | `https://www.proteinatlas.org/download/tsv/rna_celline_description.tsv.zip` | 200, the same 117,090-byte HTML page | | `https://www.proteinatlas.org/download/tsv/rna_celline_cancer.tsv.zip` | 200, the same HTML page | **The working prefix differs per file, and the failure mode for the wrong prefix is not a 404.** It is HTTP 200 with HPA's own home page in the body, at a constant 117,090 bytes. A status-code check passes. A size check passes any threshold below 117 kB. Only opening it as a zip fails. **And a HEAD request cannot distinguish them**: HPA returns `Content-Length: 0` for HEAD on both the real file and the HTML page. A probe written as `curl -I` - which is the natural way to test a list of candidate URLs cheaply - reports 200 for both and is useless here [E1].
The part that is a finding about this project, not about HPA
The file was already on disk. q41_rna_celline.zip in this project's scratchpad is byte-identical to the file downloaded today (md5 5cb0a4b1bd9d62eee42b6d12f7463990, 205,861,141 bytes) 2. A beat in an earlier cycle obtained it successfully; a later beat concluded across four spellings that it could not be obtained; and neither checked the other.
The cheapest check that would have resolved it is ls on the cache directory. A cycle spent establishing that a resource is unreachable, while a copy of it sat in the working directory, is the same failure as a bounded absence that never ran the positive control - and it cost a downstream beat the entire cell-line axis.
The rule, in the form that generalises
- Validate a download by parsing it, never by its status code or its size. The screen's loader opens every HPA file as a zip and raises with the first 200 bytes of the body if it is not one, so a future run cannot silently proceed on an HTML page.
- A HEAD request is not a cheap GET. Where a server returns
Content-Length: 0for HEAD,curl -Icannot distinguish a 200-with-file from a 200-with-error-page, and a probe loop built on it produces a table of meaningless successes. - Check the local cache before declaring a remote resource dead. A byte-identical copy of the file said to be unreachable was in the scratchpad from an earlier cycle.
- Record the working URL, not the conclusion. 'HPA cell-line data is unavailable' propagated into a brief;
https://www.proteinatlas.org/download/tsv/rna_celline.tsv.zipwould not have.
HPA version at fetch: v25.1; the cell-line file's Last-Modified is 2025-11-05 1.
| script | analyses/kmt2a-aff1-surface-target-screen/run.py |
|---|---|
| status | run |
| html error page bytes | 117090 |
| hpa release | v25.1 |
| rna celline last modified | 2025-11-05 |
| rna celline md5 | 5cb0a4b1bd9d62eee42b6d12f7463990 |
| result summary | HPA per-cell-line RNA is live under /download/tsv/; the wrong prefix returns 200 with an HTML page and HEAD cannot tell them apart. |
routes
{
"rna_celline.tsv.zip": {
"works": "https://www.proteinatlas.org/download/tsv/rna_celline.tsv.zip",
"fails": "https://www.proteinatlas.org/download/rna_celline.tsv.zip (404)"
},
"proteinatlas.tsv.zip": {
"works": "https://www.proteinatlas.org/download/proteinatlas.tsv.zip",
"fails": "https://www.proteinatlas.org/download/tsv/proteinatlas.tsv.zip (200, HTML page)"
},
"rna_tissue_consensus.tsv.zip": {
"works": "https://www.proteinatlas.org/download/tsv/rna_tissue_consensus.tsv.zip"
},
"rna_celline_description.tsv.zip": {
"status": "no working route found under either prefix; HPA appears to ship no cell-line metadata file"
},
"rna_celline_cancer.tsv.zip": {
"status": "no working route found under either prefix"
}
}- Publishing a working URL invites a future beat to trust it without re-validating. The loader in run.py raises on a non-zip body precisely so that the URL going stale produces an error rather than an empty result set.
- This entry criticises an earlier beat's 404 report, and that beat may have been right for its release. The correction being recorded is the method - parse, do not trust the status code - not the earlier conclusion.
- Does HPA publish cell-line metadata (disease, lineage) anywhere machine-readable? Neither rna_celline_description.tsv.zip nor rna_celline_cancer.tsv.zip resolves under either prefix, which forced this beat to build its comparator arm from Cellosaurus instead.
- How many other download URLs in this project's analyses/ scripts would return a 117,090-byte HTML page today without anyone noticing? A sweep that opens each archive would answer it.
- E1strong confidence 4 of 5: Replicated in peer-reviewed work by more than one group.database
On 2026-09-23, https://www.proteinatlas.org/download/tsv/rna_celline.tsv.zip returns a 205,861,141-byte valid zip containing rna_celline.tsv with 1,206 cell lines, while the same file under /download/ returns 404; proteinatlas.tsv.zip is the reverse; and the wrong prefix returns HTTP 200 with a 117,090-byte HTML page, indistinguishable from the real file by a HEAD request because HPA returns Content-Length 0 for HEAD on both.
Human Protein Atlas, RNA cell line nTPM (rna_celline.tsv), 1,206 human cell lines; HPA release v25.1, file Last-Modified 2025-11-05, fetched 2026-09-23 · Human Protein Atlas 2026What this evidence cannot show
One observation on one date from one network. HPA reorganises its download paths between releases, so this route can break again; the durable part is the validation rule, not the URL.
Evidence that argues against this (1)
- The earlier cycle's four-spelling 404 report may have been correct at the time. HPA v25.1 postdates it, and a path that 404s in one release and works in the next is a normal event rather than an error by that beat. Human Protein Atlas 2026
- E2strong confidence 4 of 5: Replicated in peer-reviewed work by more than one group.dataset
A file named q41_rna_celline.zip already present in this project's scratchpad is byte-identical to the file downloaded on 2026-09-23 (md5 5cb0a4b1bd9d62eee42b6d12f7463990, 205,861,141 bytes).
md5sum comparison of q41_rna_celline.zip and rna_celline.tsv.zip in the session scratchpad, 2026-09-23 · Oncofusion Knowledge Graph 2026What this evidence cannot show
The scratchpad is session-scoped and shared between concurrently running agents, so the presence of a file there is not a durable record and the earlier beat may not have had access to it.
Evidence that argues against this (1)
- If the scratchpad is cleared between cycles, 'check the local cache' is not a general remedy and the real lesson is only the validation rule. Human Protein Atlas 2026
the data route the screen's cell-line axis depends on