Skip to Content
ReferenceErrors

Errors

Every failure mode has its own type, so a caller can tell a reference mismatch from a naming mismatch without parsing English. This page is organised by what you saw; the API reference has the class details.

Start here

What you sawWhat it isGo to
ContigNamingErrorchr1 against 1Naming
ContigOrderErrorSame contigs, different orderOrder
ReferenceFrameErrorThe reference is not the genome a step’s coordinates meanFrame
DimensionErrorTwo inputs disagree about somethingDimensions
UndeclaredDimensionErrorSomething must be declared and was notUndeclared
StepTypeErrorA step was handed the wrong kind of dataTypes
StepDefinitionErrorThe step itself cannot be used as oneDefinition
LoadErrorA file would not readLoading
RunErrorA step failed while runningRunning
A noticed line, not an errorA tool named a sample after a fileNotes
check passed but results look wrongNot a Ligase errorWhen check is not enough

How they relate

Everything found before anything runs is a CheckError. That is the useful distinction: a CheckError cost you milliseconds, anything else cost you a run.

Exception ├── CheckError found by `check`; nothing has run │ ├── DimensionError two inputs disagree │ │ ├── ContigNamingError ... about naming style only │ │ ├── ContigOrderError ... about contig order only │ │ ├── ReferenceFrameError ... about which genome the numbers mean │ │ └── UndeclaredDimensionError │ └── StepTypeError wrong kind of data for the step ├── LoadError a file would not read └── RunError a step failed while running TypeError └── StepDefinitionError the decorated function is not usable

Catching CheckError catches all six of the first group. Catching DimensionError catches the naming and order cases too, which is usually what you want; catch ContigNamingError on its own only when you mean to treat naming differently from everything else.

import ligase as lg try: pipeline.check() except lg.ContigNamingError as e: # Specifically a naming mismatch: a renaming step would fix it. print(e.step, e.dimension) except lg.CheckError as e: # Anything else found before compute. `e.errors` has all of them. for problem in e.errors: print(problem)

ContigNamingError

The same contigs under different names — chr1 against 1. The engine has checked that the contigs are otherwise identical, which is why this is its own type rather than a reference mismatch.

Fix it by using one naming convention throughout, or by inserting a renaming step. Full worked explanation, with the real diagnostic: my BED file intersects nothing.

ContigOrderError

The same contigs, in a different order. htslib matches contigs by name and does not care; GATK requires matching sequence dictionary order and will refuse. Reported because silence would hide a failure in a tool you may add tomorrow.

GATK rejects my sequence dictionary.

ReferenceFrameError

The reference is not the genome a step’s own coordinates are counted along. Most dimension errors are two inputs disagreeing; this one is an input disagreeing with the engine. lg.hivdb.interpret holds the HIV-1 gene windows as positions in HXB2 K03455 counted from its first base, and a reference numbered any other way puts a different gene under each window.

The case that matters is a pol-relative reference — K03455 2085–5096, so every position 2084 lower. Protease’s window then lands in integrase, and before this error existed the report came back with protease-inhibitor resistance at a clinical level.

ReferenceFrameErrorin stepresistanceligase check — nothing ran
ref.reference=K03455 (3012 bp)from FASTA contigs: crates/ligase-core/tests/fixtures/hivdb_pol.fasta
resistance reads positions in K03455 from base 1 (9719 bases) (built into this engine)
The reference is 3012 bases long and the gene windows reach base 5093, so they cannot all land on the genes they name; protease is read from wherever base 2253 of this file happens to be.
This engine reads whole-genome K03455 and does not shift its windows. If this is a pol-relative reference — K03455 2085..5096 is the usual slice — pad it back into the frame with `"N" * 2084 + pol` and declare `frame=("K03455", 1)`.

The fix is not a different file. It is the same sequence put back where its own numbers mean what the windows say:

ref = lg.reference( "hxb2_padded.fasta", # "N" * 2084 + hxb2_pol organism="HIV-1", frame=("K03455", 1), )

A whole-genome HXB2 reference needs no declaration — 9,719 bases identifies it — so you see this only when the reference is something else. Why the frame is declared rather than inferred: D33. The worked account, and what it cost before it was an error: my resistance report names the wrong gene.

DimensionError

Two inputs to a step disagree about a dimension. The base case, raised when the disagreement is not specifically naming or order — a different reference build, a different coordinate convention, a different sample set.

The message names both values, where each came from, and asks a leading question. The provenance is the actionable part: knowing two references disagree sends you hunting, while knowing one came from a BAM @SQ header and the other from the FASTA you passed tells you what to change.

UndeclaredDimensionError

A dimension some step requires is unknown, and must be declared. Not every dimension can be read out of a file: no FASTA records its organism, and a BAM header does not say which build it was made against.

Ask what is missing and why:

>>> aln.unknown_reason("organism") 'not recorded in SAM/BAM headers; declare it'

Then declare it once, at load:

aln = lg.alignment("data/alignments/sample01.bam", organism="human")

A dimension that no downstream step requires may stay unknown. See declaring dimensions.

StepTypeError

A step was handed a kind of data it does not declare. A Variants where the signature says Alignment. Blames no dimension — dimension is None on this one — because the problem is the type, not a value within it.

Usually an argument in the wrong position, or a step whose return annotation does not match what the next step takes.

StepDefinitionError

The decorated function cannot be used as a step, raised at definition time rather than at check time. A parameter with no annotation, a missing return annotation, or an annotation the graph cannot interpret.

This one subclasses TypeError, not CheckError, because it is a mistake in the code rather than in the data.

LoadError

A file could not be read, or did not parse as the format expected. The path is wrong, the file is truncated, or a .fasta is not a FASTA.

Raised by every loader — lg.reference, lg.alignment, lg.variants, lg.reads, lg.intervals, lg.entity_set, lg.ranked_list, lg.samples and lg.remote — at the point of loading, so it names the file.

It is also what a molecule table gets when its own keys refute the standardisation it claims. cannot read <file> in the state it says it is in means the table is declared charge-neutralised — by an argument, or by the representation line in the file — and at least one of its InChIKeys is not: the third block of a key is its protonation layer, and N is the only value it takes for a molecule with no proton added or removed. The message names the key, the row and the state those keys are in. Nothing else about a representation is checked, because nothing else about one leaves a trace in a key.

RunError

A step failed while running. Carries a report with the whole run’s outcome and a failures list of StepFailure, each naming its step, its node and the sample it stood for.

This is the one class of error that cost you compute. Everything the cache had already is still there, so fixing the step and running again does not redo the work above it.

try: pipeline.run() except lg.RunError as e: for failure in e.report.failures: print(failure.step, failure.sample, failure.message)

When check is not enough

check compares dimensions. It cannot tell you that your aligner’s settings were wrong, that your reads are contaminated, or that a threshold is inappropriate for your question. A pipeline that checks clean can still be scientifically wrong.

Two things help with the part Ligase can speak to:

  • ligase audit <step> runs a step twice and reports whether it repeats. Non-determinism that the cache would hide shows up here. See semantic hashing and auditing.
  • ligase methods --verify checks a reproducibility bundle against what this machine produces, which catches an environment that has drifted.

And a noticed line in a run report is neither an error nor nothing: it is the engine telling you something about your data it could not refuse over. The common one is a tool naming a sample after a file, which happens when an alignment carries no @RG SM tag — see reading what the engine noticed.

Last updated on