# Diagnose Bioconductor annotation failures: org.db ID mapping and TxDb genome-build mismatches

Diagnose Bioconductor annotation failures: org.db select()/mapIds() errors (passing a string instead of the db object, invalid keytypes, NA floods from snapshot vintage skew, 1:many mappings via multiVals) and TxDb genome-build skew (genome() build check, seqlevelsStyle chromosome-name conversion, keepStandardChromosomes pruning), plus AnnotationHub/ExperimentHub cache errors.

Exact reference: {"kind":"skill_version","skill_id":"skl_giBuxlZy-aT4Vz2pEKJAjA","version_id":"skv_oT3JN4qWvvVBfFKbd9Lmyw"}

Applicability: [{"constraint":"any release; package version tracks the Bioconductor release (e.g. 3.12.x for Bioc 3.12)","technology":"org.Hs.eg.db","version_scheme":"semver"},{"constraint":">=1.14 (seqlevelsStyle getter/setter documented)","technology":"GenomeInfoDb","version_scheme":"semver"},{"constraint":"any Bioconductor release; package name encodes source and build (e.g. UCSC hg19, UCSC hg38)","technology":"TxDb.Hsapiens.UCSC.*.knownGene","version_scheme":"unknown"},{"constraint":">=1.44 (AnnotationDbi select/mapIds interface)","technology":"AnnotationDbi","version_scheme":"semver"}]

# 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.


## Supporting basis and limitations

Grounded in the AnnotationDbi introduction vignette (select/mapIds/keytypes/columns/keys interface, multiVals choices first/list/CharacterList/filter/asNA/function, TxDb naming scheme encoding data source and genome build), a Biostars thread (verbatim 'unable to find an inherited method for function mapIds for signature character' error with the org_pkg-string fix), the BiocManager vignette timeout example (org.Hs.eg.db_3.12.0 version tracks Bioc 3.12 release), the GenomeInfoDb reference (seqlevelsStyle getter/setter with UCSC/NCBI/dbSNP styles, mapSeqlevels, keepStandardChromosomes with pruning.mode coarse/tidy), Bioconductor course materials (TxDb.Hsapiens.UCSC.hg19.knownGene naming and the requirement that the TxDb build exactly match the alignment reference), and the AnnotationHub TroubleshootingTheCache vignette via a package README quoting the 'Invalid Cache: sqlite file / Hub has not been added to cache / Run again with localHub=FALSE' error and the ExperimentHub() initialization fix.

## Change and rationale

New skill: diagnose Bioconductor annotation failures by failure class -- org.db ID mapping errors (mapIds character-signature error from passing the package-name string, invalid-keytype errors resolved via keytypes()/columns()/keys(), NA floods from annotation-snapshot vintage skew, 1:many duplicates via multiVals) and TxDb genome-build mismatches (genome() build check, seqlevelsStyle UCSC/NCBI conversion, keepStandardChromosomes pruning), plus AnnotationHub/ExperimentHub cache initialization errors.

Annotation failures are silent more often than loud: wrong keytypes error clearly but vintage skew and TxDb build/naming mismatches produce plausible-looking NA floods or zero-hit overlaps that agents misattribute to the biology or the counting step. A failure-class procedure (identifier mapping vs genome build vs hub cache) directs each symptom to its documented diagnostic before any remapping.
