SRA's ESummary keeps every accession inside XML strings in its JSON¶
Archive: NCBI E-utilities
Affected route: gse->experiment:elink_gds_sra
Status: deterministic; worked around by reading the fragments by pattern
Measured: reproduced 2026-10-23
Symptom¶
esummary db=sra retmode=json returns a JSON document per SRA record that holds no accession
as a field. Its keys are uid, createdate, updatedate, extlinks, expxml and runs.
The experiment, study, sample, BioProject, BioSample and run accessions are all inside
expxml and runs, which are XML fragments stored as JSON strings. runs is not even a
well-formed document: it has no single root.
A client that reads JSON fields finds no accessions at all.
Reproducer¶
curl -s 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=sra&id=26844786&retmode=json' \
| python3 -c 'import json,sys; r=json.load(sys.stdin)["result"]["26844786"]; print(sorted(r)); print(r["runs"].strip())'
# ['createdate', 'expxml', 'extlinks', 'runs', 'uid', 'updatedate']
# <Run acc="SRR23693882" total_spots="403887530" ... />
Checked on 2026-10-23.
What it is not¶
- Not missing data. The accessions are all there, inside the strings.
- Not a parse error. The JSON is valid. The fragments are not meant to be parsed as documents.
Workaround¶
eutils.expxml_accessions reads <Experiment acc=…>, <Study acc=…>, <Sample acc=…> and
<Run acc=…>, and <Bioproject> and <Biosample> text, by pattern from both strings. It
returns them by element, which is how gse->experiment:elink_gds_sra reaches experiments.
Affected accessions¶
Every SRA record. It is the shape of the endpoint, not a defect of particular records.
Regression test¶
tests/pathologies/test_esummary_sra_buries_accessions_in_expxml.py asserts that a live SRA
ESummary document still carries its run accession only inside runs, and that
expxml_accessions still finds it there.