Skip to Content
Silent failuresWhat goes wrong silently

What goes wrong silently

Every page in this section is a bug that does not raise an exception, does not log a warning, and does not change the shape of the output. It produces a file of the right size, in the right format, with plausible numbers in it. The only way to find it is to check before computing, or to catch it in review.

These are not hypothetical. Most are documented hazards with a literature of their own, and each has an entry in Ligase’s dimension catalogue because it was worth building a type system to prevent. One of them — a resistance reference not in the frame the gene windows mean — was found in this engine, by somebody evaluating it for real work.

chr1≠1My BED file intersects nothing

UCSC names contigs chr1; Ensembl and NCBI name them 1. Tools match by name, find no overlap, and report zero.

GRCh37≠GRCh38My variant positions are wrong

Reads aligned against one build, variants called against another. Positions are valid, and refer to the wrong place.

0-based≠1-basedMy intervals are off by one

BED counts from zero and excludes its end; GFF counts from one and includes it. Mixing them moves every boundary by a base.

[a, b]≠[b, a]My sample labels look swapped

Two files with the same cohort in a different column order. Every genotype is attributed to the wrong person.

1%≠5%My paper and my pipeline disagree

A threshold moved and the sentence reporting it did not. The pipeline is correct, the output is correct, and a number in the manuscript is now wrong with nothing anywhere connecting the two.

TP53≠ENSG00000141510My gene-set overlap is empty

Two gene lists named in different identifier spaces. The join succeeds and the intersection is empty, which reads as a biological result.

…SA-M≠…SA-NMy compound overlap is almost empty

Two compound sets standardised differently. The same substance has a different InChIKey in each, the overlap is small rather than zero, and no glance at two columns of keys can tell them apart.

…JTQLQIEISA…≠…UHFFFAOYSA…My inactive enantiomer came back as a hit

Tautomer normalisation discards stereochemistry, so two enantiomers become one InChIKey. This one makes an overlap too large: a join matches a pair that is not a pair, and half of those matches are the compound you did not mean.

3 sources≠4 sourcesMy target ranking changed and I cannot find the analysis change

Two knowledge graphs assembled from different evidence sources. Every score is computed correctly, and the ranking moved because the graph was rebuilt rather than because the biology did.

HIV-1≠HIV-1 + humanMy pathogen results include host reads

A host–pathogen sample declared as only its pathogen. The declarations agree, so nothing objects while host reads are called as viral variants.

pol 1..≠K03455 2085..My resistance report names the wrong gene

A pol-relative reference against gene windows stated in whole-genome coordinates. The window named protease lands in integrase, and the report reads the same either way.

2, 1≠1, 2GATK rejects my sequence dictionary

The one in this list that is loud — but only in some tools, which is its own kind of trap.

What these pages show

Each page states the bug, explains why nothing crashed, and then shows the diagnostic Ligase produces for it.

The diagnostics are not written for these pages. They are captured from a real run of the engine by web/scripts/capture_diagnostics.py on every docs build, against the committed test fixtures, and the build fails if the engine stops producing the error a page claims it produces. What you read here is what you would see in your terminal.

The general shape of the fix

In every case the fix is the same two moves: declare what the files cannot say about themselves, then let check() compare the whole graph before anything runs.

import ligase as lg ref = lg.reference("data/refs/GRCh38.fasta", organism="human", build="GRCh38") aln = lg.alignment("data/alignments/sample01.bam") pipe = lg.Pipeline(call(aln, ref)) pipe.check() # reads headers only; no compute

organism and build are declared because no FASTA records them. Everything else — contig names, lengths, MD5s, coordinate convention, sample set — is read out of the files, so it cannot be declared wrongly.

See declaring dimensions for the walkthrough and the dimension catalogue for what is inferred from which format.

Last updated on