# Diagnose Bioconductor annotation failures: org.db ID mapping and TxDb genome-build mismatches
Use this when `select()` / `mapIds()` on an `org.*.db` package returns all NAs,
throws keytype errors, or gives 1:many mappings you did not expect — or when
coordinates from a `TxDb` package disagree with your data (silently empty
overlaps, gene positions that look wrong). Annotation failures split into
identifier-mapping failures and genome-build failures; classify which you have
before remapping anything.
## 1. Failure class A: org.db ID mapping errors and NA floods
The org.db interface is `AnnotationDbi`: `select()`, `mapIds()`, `keytypes()`,
`columns()`, `keys()`. The package name encodes the organism and the key type —
`org.Hs.eg.db` means human, Entrez Gene central keys ('eg' = Entrez Gene).
**Step 1 — read the exact error.**
`unable to find an inherited method for function 'mapIds' for signature
'"character"'` means the first argument was a character string, not the
database object. A frequent cause: storing the package name in a variable.
```r
library(AnnotationDbi)
library(org.Hs.eg.db)
# WRONG: org_pkg is a string; mapIds has no method for character
org_pkg <- "org.Hs.eg.db"
mapIds(org_pkg, ids, "ENTREZID", "ENSEMBL")
# RIGHT: pass the loaded database object
org_pkg <- org.Hs.eg.db
mapIds(org_pkg, ids, "ENTREZID", "ENSEMBL")
```
`None of the keys entered are valid keys for 'X'. Please use the keys method to
see a listing of valid arguments.` means the `keytype` does not match the
identifier flavor you passed. Discover what the package actually offers:
```r
keytypes(org.Hs.eg.db) # identifier flavors accepted as keytype
columns(org.Hs.eg.db) # columns you may request
head(keys(org.Hs.eg.db, keytype = "ENSEMBL")) # what keys look like
```
Typical mistake: passing Ensembl IDs (`ENSG...`) with `keytype = "ENTREZID"`
or gene symbols with `keytype = "ENSEMBL"`.
**Step 2 — if there is no error but most results are NA: check the data
vintage.** org.db packages are rebuilt from the current NCBI/Ensembl snapshot
at each Bioconductor release, and the package version tracks the release
(e.g. `org.Hs.eg.db_3.12.0` shipped with Bioconductor 3.12). IDs retired or
renamed since your IDs were generated — versioned Ensembl IDs with the
`.11` suffix that changed, withdrawn symbols, merged Entrez records — return
NA because they no longer exist in the snapshot:
```r
packageVersion("org.Hs.eg.db") # which snapshot you are mapping against
sum(is.na(symbols)) # how many keys failed to map
```
Fixes: strip Ensembl version suffixes (`sub("[.].*$", "", ids)`) if the
snapshot predates them, match the org.db vintage to the vintage that produced
the IDs, and accept that a small NA fraction is normal (withdrawn records),
not a bug in your code.
**Step 3 — duplicate mappings are expected; choose the resolution.** Gene
identifiers are often 1:many. `select()` returns all rows; `mapIds()` requires
`keytype` and takes a single `column`, resolving duplicates via `multiVals`
(default `"first"`). Alternatives: `"list"`, `"CharacterList"`, `"filter"`,
`"asNA"`, or a user-supplied function:
```r
mapIds(org.Hs.eg.db, ids, "SYMBOL", "ENSEMBL", multiVals = "list")
```
If a script "worked" on an old org.db and now returns different symbols, the
vintage changed, not the code — pin the package version.
## 2. Failure class B: TxDb genome-build and chromosome-name skew
TxDb package names encode the source and the genome build, e.g.
`TxDb.Hsapiens.UCSC.hg19.knownGene` (UCSC, hg19, knownGene track). The
current-build counterpart follows the same scheme with `hg38`. Two independent
things must agree with your data: the build and the chromosome naming.
**Step 1 — confirm the build.** The coordinates in a TxDb are only valid for
its build:
```r
library(TxDb.Hsapiens.UCSC.hg38.knownGene)
txdb <- TxDb.Hsapiens.UCSC.hg38.knownGene
genome(txdb) # e.g. "hg38" -- must match the reference your reads were aligned to
```
If the alignments used hg38 and the TxDb is hg19, overlaps and gene
coordinates are silently wrong — nothing errors, the numbers just disagree.
There is no automatic fix; install the TxDb for the build that matches the
data.
**Step 2 — confirm the chromosome-name style.** `findOverlaps()` matches the
triplet (seqname, range, strand), so `chr1` in your data vs `1` in the TxDb
yields zero hits with no warning. Check and convert with GenomeInfoDb:
```r
library(GenomeInfoDb)
seqlevelsStyle(txdb) # e.g. "UCSC" (chr1) vs "NCBI" (1)
seqlevelsStyle(txdb) <- "NCBI" # renames chr1 -> 1, chrM -> MT, etc.
```
Do the conversion on one side so both sides share a style, then re-run the
overlap. To drop unplaced scaffolds and alt contigs before comparing:
```r
txdb <- keepStandardChromosomes(txdb, pruning.mode = "coarse")
```
**Step 3 — sanity-check the overlap result, not just the code.** After
alignment of build and style, spot-check with `countOverlaps()` or
`subsetByOverlaps()` on a known gene (e.g. pull `transcripts(txdb)` for a
housekeeping gene and confirm your reads overlap it). Zero overlaps after the
build/style check points back to the counting stage, not the annotation.
## 3. Failure class C: AnnotationHub / ExperimentHub cache errors
Packages that fetch hub resources at load time can fail with:
```
error: Invalid Cache: sqlite file
Hub has not been added to cache
Run again with 'localHub=FALSE'
```
The local hub cache was never initialized or is corrupt. Initialize it first,
answering "yes" if prompted to create the local cache directory, then
re-install or re-load the package:
```r
AnnotationHub::AnnotationHub() # or ExperimentHub::ExperimentHub()
```
The AnnotationHub vignette "Troubleshooting the Cache" documents the recovery
steps for the persistent cases.
## 4. Checklist for the failing annotation step
1. Classify: A (ID mapping: error or NA flood), B (TxDb coordinates: silent
wrong/empty results), C (hub cache error at load).
2. A-error: pass the db object, not the package-name string, to `mapIds`;
discover valid flavors with `keytypes()`/`columns()`/`keys()`.
3. A-NA: compare `packageVersion("org.Hs.eg.db")` against the vintage that
produced the IDs; strip version suffixes; resolve 1:many with `multiVals`.
4. B: `genome(txdb)` must equal the alignment build; `seqlevelsStyle()` must
match on both sides — convert one side, then re-run overlaps;
`keepStandardChromosomes(..., pruning.mode = "coarse")` to drop alt contigs.
5. C: initialize the hub with `AnnotationHub()` / `ExperimentHub()` before
installing or loading.