Oncofusion

start / graph / concept-q117-the-ucsc-search-api-puts-hoxa9-on-chr1-if-you-take-the-longest-match-and-six1-on-chr17-if-you-trust-the-symbol

Explainerestablished confidence 5 of 5: Multiple independent lines of evidence; treated as settled in the field.Q117-gained-fusion-occupancy

Rule 62 applies to a genome browser: the UCSC search API returns several tracks and many rows per gene, 'take the longest' put Hoxa9 and Meis1 on chr1, only the refGene track carries the SYMBOL in posName, and xenoRefGene returns a human-aligned Six1 on mouse chr17

also called Q117 UCSC search trap · posName is an accession in ncbiRefSeqCurated

Asking a genome browser where a gene is returns many answers from many different annotation sets, and picking the biggest one silently puts famous genes on the wrong chromosome. The fix is to keep only the one annotation set that reports gene symbols and to require an exact match.

The same thing, for a scientist

`https://api.genome.ucsc.edu/search?search=<symbol>&genome=mm10` returns `positionMatches` as a **list of groups, one per annotation track**, each with many rows. The obvious resolver - accept the RefSeq-like tracks and take the longest interval - produced, in this beat, **identical chr1 windows for Hoxa9 and Meis1 and identical chrX windows for Six1 and Ncor1**, and the error was caught only because two different genes returned the same numbers [E1]. Three distinct mechanisms, all verified live on 2026-09-23 [E1]: 1. **`posName` is not always the symbol.** In `ncbiRefSeqCurated` it is the RefSeq accession - `NM_010456.3` for Hoxa9 - so a filter requiring `posName == symbol` silently discards that track. **Only `refGene` reports the symbol in `posName`** (`Hoxa9`, with a `description` of `(NM_010456) homeobox protein Hox-A9 isoform 1`). 2. **`xenoRefGene` matches the symbol and is a different species.** For Six1 it returns `chr17:85,685,183-85,687,946` with `posName: Six1` - a human transcript aligned onto the mouse genome, at a locus 13 Mb and one chromosome away from the real mouse *Six1* at `chr12:73,041,827-73,046,712`. **A symbol-exact filter does not exclude it.** 3. **'Longest wins' is the wrong tie-break across tracks.** `wgEncodeGencodeCompVM25` and `knownGene` carry long readthrough and merged models, so the longest row for a symbol is routinely not the gene. **The correct resolver is three lines**: keep the group whose `trackName` is exactly `refGene`; keep only rows whose `posName`, case-folded and stripped, equals the symbol asked for; then take the longest of *those*. With that filter Hoxa9 resolves to `chr6:52,223,097-52,227,370`, Meis1 to `chr11:18,880,428-19,018,969` and Six1 to `chr12:73,041,827-73,046,712` [E1]. **The tell that caught it, and the one worth internalising: two different genes returned identical coordinates.** Nothing in the API response is malformed and no error is raised; the only signal is that the answer for *Hoxa9* and the answer for *Meis1* were the same 138 kb window on chr1. A resolver that is wrong for one gene at a time produces a plausible table.

Go deeper
Why this belongs beside the UniProt rules and not apart from them

This graph already records that gene_exact:TRAF2 returns TANK first, that gene_exact:HDAC7 returns HDAC9 first with a protein name containing HD7, and that CSNK2A1 is an alias of CSNK2A2. The shape is identical here: a lookup returns several rows, the code takes one, and the one it takes is chosen by a criterion that has nothing to do with correctness. The remedy is the same - match on the field that carries the primary identity, read every row, and stop if none or more than one matches.

What is new is the cross-species row. UniProt's traps are all within-species; xenoRefGene is a track of other organisms' mRNAs aligned onto this genome, and it carries the other organism's symbol. A coordinate resolver that filters on symbol alone and not on track will happily return a human gene's mouse alignment.

Facts and figures
domainresearch method
ruleWhen resolving a gene symbol to coordinates through the UCSC search API: keep the group whose trackName is exactly 'refGene'; keep only rows whose posName equals the symbol; take the longest of those; then assert that the resolved intervals across your gene set are pairwise distinct.
registry noteThis is a genome-browser lookup trap, not a gene-symbol collision, and it is NOT in data/symbol-collisions.json. Reported here rather than written there because this beat does not own that file.
verified examples
{
  "Hoxa9": {
    "correct": "chr6:52223097-52227370",
    "refGene_posName": "Hoxa9",
    "ncbiRefSeqCurated_posName": "NM_010456.3"
  },
  "Meis1": {
    "correct": "chr11:18880428-19018969",
    "refGene_posName": "Meis1"
  },
  "Six1": {
    "correct": "chr12:73041827-73046712",
    "xenoRefGene_decoy": "chr17:85685183-85687946 posName Six1 (human NM_001290088 aligned onto mouse)"
  }
}
failure modes
[
  "posName is a RefSeq accession in ncbiRefSeqCurated and ncbiRefSeqPredicted, not a symbol",
  "xenoRefGene carries the other organism's symbol on this organism's coordinates",
  "longest-interval tie-break across tracks selects readthrough and merged models",
  "the API raises no error and returns a well-formed answer in every case"
]
How this could bite us back
  • A wrong coordinate produces a real number from real data at a real locus, so every check downstream passes. In this beat it would have produced a FLAG occupancy ratio for 'Hoxa9' that was actually a chr1 window, in a table whose whole purpose was to test a published claim about the HOXA cluster - and the conclusion drawn from it would have been the opposite of the right one.
Still open
  1. Does the same trap exist for hg38, where this project does most of its work? The track set differs by assembly and xenoRefGene is present for hg38 too, so the answer is probably yes and nobody has checked.
  2. How many coordinates in this graph were resolved through a search endpoint rather than a downloaded annotation table, and were any of them resolved with a longest-match rule?
Every source behind this entry (2)
  1. E1established confidence 5 of 5: Multiple independent lines of evidence; treated as settled in the field.database

    The UCSC mm10 search API returns Hoxa9 under posName NM_010456.3 in ncbiRefSeqCurated and under posName Hoxa9 in refGene, returns a human-aligned Six1 at chr17:85,685,183-85,687,946 in xenoRefGene against the true mouse Six1 at chr12:73,041,827-73,046,712, and a longest-match-across-tracks resolver returned identical chr1 windows for Hoxa9 and Meis1.

    What this evidence cannot show

    Observed on 2026-09-23 against the live endpoint. The exact chr1 and chrX windows the broken resolver returned were not recorded before the resolver was fixed; what was recorded, and is reproducible from the locus table's first version, is that Hoxa9 and Meis1 returned identical chr1 coordinates and Six1 and Ncor1 identical chrX coordinates. The track list returned by the endpoint depends on which tracks are loaded for an assembly, so the specific set named here is mm10's and may differ for hg38.

    Evidence that argues against this (1)
    • Restricting to refGene is itself a choice with costs: refGene is a curated RefSeq subset and will miss genes that have only a GENCODE or predicted model, returning a clean 'no match' where a gene exists. For a beat working on named, well-studied loci that is the right trade; for an unbiased genome-wide join it is not, and the right answer there is a downloaded annotation table rather than a search endpoint at all. UCSC Genome Browser 2026
  2. E2established confidence 5 of 5: Multiple independent lines of evidence; treated as settled in the field.database

    The error was detected because two different genes returned identical coordinates and identical downstream values, not by any error from the API.

    What this evidence cannot show

    A single detection event. If the table had contained only one affected gene, nothing would have flagged it, and the beat would have published a FLAG occupancy ratio for Hoxa9 measured at a chr1 locus. The detection depended on the table being long enough to contain a collision, which is luck rather than design.

    Evidence that argues against this (1)
    • A duplicate-coordinate check is cheap and general and should not be left to luck: after resolving a set of symbols, assert that the resolved intervals are distinct, and assert that each resolved interval's chromosome matches an independent source. Neither assertion was in this beat's script when the bug fired; the first is now the obvious addition. UCSC Genome Browser 2026
Connected to