Skip to content

ENA's derived fastq omits the read that carries the cell barcode

Archive: EBI ENA Affected route: run->file:ena_fastq Status: detected, measured, and worked around; ready to report upstream Measured: 2026-09-15 on a random 3,000-run sample of the reprocessed corpus

The number

1,177 of 3,000 runs — 39.2%.

For that many runs of a 10x corpus, ENA's fastq_ftp serves a single file for a library ENA itself declares PAIRED, and the SRA archive holds more bases than ENA publishes. Across the affected runs:

Bases SRA holds 19.1 Tb
Bases ENA does not publish 5.93 Tb (31.1%)
Median SRA/ENA base ratio 1.40
SRA avgLength for 83% of them 120–139 bp

An avgLength of 120–139 with a published read of ~91–98 bp is a spot holding a ~28 bp read alongside the long one. That short read is the 10x cell barcode and UMI. It is not published.

Why this is worse than a missing file

The download succeeds. The checksum matches — ENA publishes a correct fastq_md5 for the partial file. The file is valid fastq. The reprocessing run completes and produces a count matrix in which every read is unassignable to a cell, because the barcode was never fetched. The failure presents as a bad experiment rather than a bad download.

Nothing in the file listing says so. The only signal is that library_layout says PAIRED beside a one-file list — two fields nothing tells you to compare.

Reproducer

# ENA: one fastq, library declared PAIRED
curl -s 'https://www.ebi.ac.uk/ena/portal/api/filereport?accession=SRR29534765&result=read_run&fields=library_layout,fastq_ftp,read_count,base_count&format=tsv'
# PAIRED  ftp.sra.ebi.ac.uk/vol1/fastq/SRR295/065/SRR29534765/SRR29534765.fastq.gz  89275969  9016872869

# SRA: the same run, 3.0 Gb more
curl -s 'https://trace.ncbi.nlm.nih.gov/Traces/sra-db-be/sra-db-be.cgi?rettype=runinfo&term=SRR29534765' \
  | python3 -c 'import sys,csv; r=next(csv.DictReader(sys.stdin)); print(r["spots"], r["bases"], r["avgLength"])'
# 89275969  12052255815  135

Same spot count. 135 bases per spot in SRA; 101 published by ENA.

And the published reads say which one survived — the FASTQ headers are tagged /3, the third read of the spot:

curl -s -r 0-200000 'https://ftp.sra.ebi.ac.uk/vol1/fastq/SRR295/065/SRR29534765/SRR29534765.fastq.gz' | gzip -dc | head -1
# @SRR29534765.1 K00337:202:HWNYLBBXX:6:1101:2747:1297/3

Confirmed by the reads, 2026-10-20

The number above was measured from metadata: a listing, a declared layout and a base count. The content survey read the files. It read the first 100,000 reads of every file ENA lists for 500 runs drawn from the same 3,000, and applied the fit rule to them.

ENA's listing in the census Fit Unfit Undetermined
one fastq 0 183 0
two or more 234 1 56

Every one of the 183 single-fastq runs is proven unusable by its reads. None holds a read whose first 16 bases are a listed 10x barcode, or none holds a read long enough to be the cDNA. For 142 runs with an unfit ENA fastq, NCBI's Normalized SRA object of the same run is fit. (Read on 2026-10-22 under fit-3, judged under fit-5; the first reading, under fit-2, found 182 and 141.)

The reads also found a defect the listing cannot see. SRR14522447 has two ENA fastqs, of 28 and 99 bases. NCBI's Normalized object holds the same 127 bases per spot split as 8, 28 and 91. ENA's split puts the index read and the first 20 barcode bases in one read, so no read starts with a barcode. The SRA Lite object carries the same wrong split. Two files are listed, so the check on this page passes the run. Only the reads catch it.

What it is — and is not

It is ENA's derivation, not a broken deposit. Of the 1,201 single-fastq runs checked, 1,177 (98.0%) have more bases in SRA than ENA publishes. Only 11 hold the same in both, and those are genuine submitter errors: a library declared PAIRED where only one read was ever deposited (SRR30132199 is one — 28 bp reads, 52.8 M spots, identical in both archives, and unrecoverable).

Separating the two matters. A report that conflates them is useless to either archive: EBI can fix the first and only the submitter can fix the second.

There is usually nothing else to fall back to. Only 8.2% of runs in the same sample have any submitted_ftp file at all. For the rest the SRA object, reached through NCBI SDL, is the sole complete source — which is why the file layer asks every route rather than the first that answers.

Expected

Any one of: publish the technical read; report library_layout=SINGLE for what is being served; or add a field saying the derived fastq is a partial representation of the run. Excluding technical reads is a defensible default for bulk RNA-seq. For single-cell it removes the only thing that makes the reads single-cell — and the metadata gives a client no way to notice.

Detection and workaround

Mechanical and free: library_layout == PAIRED and len(fastq_ftp) == 1. fetch_series.files.Candidate.demonstrably_incomplete implements it, and recommend() ranks such a set below every format that is merely inconvenient, so an affected run resolves to the SRA object instead:

SRR29534765: no route offered a complete read pair
  -> run->file:sdl: 1 sra file, md5 published
     run->file:ena_fastq: 1 fastq file, INCOMPLETE: archive declares the library paired

The check applies only to fastq sets. A single BAM for a paired library is exactly right — a BAM carries both mates interleaved.

The incumbent reaches the same verdict by a different route. fetch10xmeta requires ENA to offer both _1.fastq.gz and _2.fastq.gz before it will use ENA fastq at all. That is a name test standing in for a completeness test: it catches all 1,177 of these, and also rejects the 24 genuinely single-end libraries in the same sample, which library_layout distinguishes.

Affected accessions

The full list of 1,177 regenerates from the survey cache:

uv run fetch survey run --route run->file:ena_fastq --corpus sample:3000@reprocessed-srr

Worked examples on this page: SRR29534765, SRR30132199 (the submitter-error case), and all 15 runs of ERP129702 / E-MTAB-8060, where the submitted BAM makes the loss visible by comparison — 25.7 GB of fastq against a 50.2 GB BAM.

Regression test

tests/test_files.py::TestDeclaredPairedButUnpaired — the flag fires on a paired declaration with one fastq, and does not fire on a single library, an undeclared layout, or a BAM; a genuine pair still outranks everything.

Seen in the reads

fetch inspect reads both copies and calls them. For SRR29534765, ENA's fastq is one file of 101-base reads named /3, and is unfit: there is no barcode read in it. The SRA object holds 8 + 26 + 101 bases and is called 3' v2. fetch files --inspect refuses the ENA set on that evidence.