IGL

Isotope Geochemistry Language, a text format for isotopic process models



Describes IGL 0.5. Page revision 1.0, 2026-07-31.

Diagnostics

41 codes, generated from the registry the compiler's own messages are generated from. A code means the same thing in every conforming implementation, which is the point of numbering them: a model author can search for IG211 and find this page rather than a forum.

igl explain IG211 prints the same text in a terminal.

CodeSeverityPhaseSummary
IG001errorsyntaxunexpected token
IG002errorsyntaxunterminated string
IG003errorsyntaxunknown block header
IG004errorsyntaxstatement is not indented
IG005errorsyntaxblock belongs to an unsupported profile
IG006errorsyntaxnon-ascii character outside an accepted position
IG007errorsyntaxmalformed expression
IG008errorsyntaxunknown or malformed unit
IG009errorsyntaxnamed block is missing its identifier
IG010warningsyntaxblock identifier does not begin with an uppercase letter
IG011warningsyntaxa block this implementation does not honour
IG101errorsemanticreference to an undeclared entity
IG102errorsemanticduplicate name in the global namespace
IG103errorsemanticmalformed or unknown isotope ratio
IG104errorsemanticmismatched element symbols across a ratio
IG105errorsemanticduplicate of a block that must be unique
IG106errorsemanticno reference standard resolvable for a ratio
IG107errorsemanticunresolved symbol in an expression
IG108warningsemanticlocal symbol shadows a global one
IG109errorsemanticill-formed qualified name
IG110errorsemanticassignment to a read-only symbol
IG201errorvalidationvalue outside the admissible range
IG202errorvalidationvalue does not match the expected type
IG204errorvalidationunit incompatible with the expected dimension
IG205errorvalidationunit omitted where several are admissible
IG210errorvalidationunknown property for this block type
IG211errorvalidationrequired property missing
IG212warningvalidationrecommended property absent
IG213errorvalidationmutually exclusive properties both present
IG214errorvalidationphysically inadmissible configuration
IG215errorvalidationmixing fractions do not sum to one
IG301errorexecutionsolver failed to converge
IG302errorexecutionnumerical instability
IG303errorexecutiondivision by zero during evaluation
IG304errorexecutionnegative remaining fraction
IG305errorexecutionreaction progress outside 0 to 1
IG306warningexecutiona statement the chosen progress does not read
IG401errorbackendrequired backend unavailable
IG402errorbackendbackend reported a failure
IG403errorbackendbackend communication timeout
IG404errorbackenda backend series read outside what it recorded

Syntax

Raised by the lexer and the parser, before any name is resolved.

IG001 — unexpected token

error · syntax phase

The parser reached a token that cannot appear at this position.

This is the fallback syntax diagnostic. When a more specific code applies it is emitted instead, so IG001 usually means the line does not match any statement family: an assignation, a reference, an expression, a species declaration or a list.

IG002 — unterminated string

error · syntax phase

A string literal was opened with a double quote and never closed before the end of the line. Strings do not span lines in IGL.

IG003 — unknown block header

error · syntax phase

A non-empty line starts at column 0 but does not name a known block.

Block headers are recognised only at column 0, and statements must be indented. A statement written flush left is therefore read as a block header, which is the most common cause of this diagnostic.

IG004 — statement is not indented

error · syntax phase

A line inside a block begins at column 0 but is not a block header.

See IG003: the two diagnostics describe the same mistake from opposite sides. IG004 is emitted when the token is a known statement key, IG003 when it is not.

IG005 — block belongs to an unsupported profile

error · syntax phase

The model uses a block from the Extended profile and this implementation declares Core conformance only.

Implementations must report the block rather than skip it. Silently ignoring an Extended block would produce a numerically plausible result from an incomplete model, which is worse than a refusal.

IG006 — non-ascii character outside an accepted position

error · syntax phase

Non-ASCII characters are accepted only inside string literals, and as the unit aliases 'micro sign' and 'per mille sign', which the lexer normalises to their ASCII forms.

Isotope notation is ASCII only. Typographic rendering such as a lowercase delta followed by a superscript mass belongs to report and plot backends, never to source files, structured data files or the intermediate representation.

IG007 — malformed expression

error · syntax phase

The right-hand side of an expression statement is not a valid expression.

Operators are + - * / and ^. Exponentiation is right associative and binds tighter than multiplication. A species token is not a valid operand; reach a species-valued quantity through a qualified name such as Groundwater.Cr(VI).

IG008 — unknown or malformed unit

error · syntax phase

The trailing run of a statement is not a unit the registry knows.

A unit is a product or quotient of unit factors, each optionally raised to an integer power: 1/d, mol/kgw, mg/L, m^3, J/mol/K. Composite units are registered whole rather than composed, so `mol/kgw` is one entry and `mol/kgww` is not an entry at all.

The diagnostic lists the units the property's dimension admits.

IG009 — named block is missing its identifier

error · syntax phase

A block that registers an entity carries its name on the header line.

v0.3 wrote the name on an indented line below the header. v0.4 puts it on the header, which is what makes implicit block termination unambiguous.

IG010 — block identifier does not begin with an uppercase letter

warning · syntax phase

The identifier on a block header line begins with a lowercase letter.

Entity names and chemical species are capitalised, keywords and enumerated values are not, which is what lets a reader tell them apart by shape. The rule covers block identifiers only: parameter names such as `alpha_red` are conventionally lowercase and never warn.

A lowercase entity name still parses. The warning exists because it is almost always a slip rather than a choice.

IG011 — a block this implementation does not honour

warning · syntax phase

The model uses a block the language defines and this implementation does not read. It is not refused, and the run produces everything else the model asks for; the block simply had no effect.

Reported rather than passed over, because a block that vanishes leaves a model looking as though it says something no run reads. The results are then correct for a model nobody wrote.

Distinct from IG005, which refuses a block belonging to a profile the implementation does not claim at all. Here the profile is claimed and this one construct within it is not implemented, which a conformance report should be able to say without the two being confused.

Semantic

Raised while names are resolved against the model's own declarations.

IG101 — reference to an undeclared entity

error · semantic phase

An identifier is used as a reference but no entity of the expected type carries that name.

Symbol resolution is a whole-file pass, so declaration order does not matter and a forward reference is legal. This diagnostic therefore means the name is absent from the model entirely, not that it appears too late.

IG102 — duplicate name in the global namespace

error · semantic phase

Two entities are declared under the same name.

IGL uses one global namespace for every named entity, whatever its type. A reservoir and a process cannot share a name. This is the condition for the extension pattern to work: FRACTIONATION Reduction has to designate exactly one object.

IG103 — malformed or unknown isotope ratio

error · semantic phase

An isotope ratio does not match the normative form, which is mass number followed by element symbol on both sides of a slash.

Forms accepted by earlier drafts, such as an element followed by two mass numbers, or a bare single isotope, are not valid. A fractionation is always relative, so there is no single-isotope form.

IG104 — mismatched element symbols across a ratio

error · semantic phase

The two element symbols of a ratio differ.

An inter-element ratio has no meaning in this position. The check costs nothing and catches the most frequent transcription error.

IG105 — duplicate of a block that must be unique

error · semantic phase

A block appears more than once although the registry declares it unique.

EXPORT and PLOT may repeat. Every other unnamed block occurs at most once per file.

IG106 — no reference standard resolvable for a ratio

error · semantic phase

A delta value was given for a ratio whose reference standard cannot be resolved, either from the loaded IGDB databases or from a STANDARD block.

A delta is meaningless without the standard it is measured against, and the engine needs the certified ratio to convert the delta into the internal representation.

IG107 — unresolved symbol in an expression

error · semantic phase

An identifier inside an expression matches nothing in the local scope of the enclosing block, nor in the global symbol table.

A cycle among parameter definitions reports the same code, with the full chain listed in the diagnostic.

IG108 — local symbol shadows a global one

warning · semantic phase

A block-local parameter carries the name of a global parameter.

Shadowing is legal, because forbidding it would make library-style PARAMETERS blocks fragile. It is worth a warning because it is rarely intentional.

IG109 — ill-formed qualified name

error · semantic phase

A qualified name has other than two components, or its head resolves to a scalar rather than to an entity with a local scope.

Property access does not nest: A.B is valid, A.B.C is not.

IG110 — assignment to a read-only symbol

error · semantic phase

A parameter bound from a backend export is read only.

Names introduced by an `export ... to ...` statement in a PHREEQC block are produced by the chemistry backend. Rebinding one would silently discard the computed value.

Validation

Raised while a block is checked against its schema.

IG201 — value outside the admissible range

error · validation phase

A property carries a value the domain does not admit: a negative concentration, a negative volume, a mixing fraction outside zero to one, a fractionation factor that is zero or negative.

IG202 — value does not match the expected type

error · validation phase

The value given for a property is not of the type the schema declares, or is outside the set of values an enumerated property admits.

Covers a quoted number where a number is expected, a malformed date or version literal, a species token where a string is expected, and an enumerated value the property does not list. The diagnostic prints the admissible values when the property is enumerated.

IG204 — unit incompatible with the expected dimension

error · validation phase

The unit given for a property belongs to a different dimension than the one the property expects.

IG205 — unit omitted where several are admissible

error · validation phase

A unit may be omitted only where the property admits exactly one, or where a default is declared in the UNITS block. Otherwise the value is ambiguous.

IG210 — unknown property for this block type

error · validation phase

The statement key is not part of the schema of the enclosing block.

The diagnostic lists the admissible keys, and suggests the closest one when the edit distance is small enough.

IG211 — required property missing

error · validation phase

The block schema declares a property as required and it is absent.

For PROCESS, the required set depends on the value of `type`. A mixing process requires two or more sources and a product, and requires neither reactant nor mechanism.

IG212 — recommended property absent

warning · validation phase

A property marked as recommended is absent. Execution proceeds.

The recommended keys of META exist for reproducibility, not for computation. A published model without a language version or a description is harder to reuse than one that carries them.

IG213 — mutually exclusive properties both present

error · validation phase

A block declares more than one member of an exclusive group.

A FRACTIONATION block carries exactly one of alpha, epsilon, an inline law, a law reference or a law file. Two of them would leave the fractionation factor undetermined.

IG214 — physically inadmissible configuration

error · validation phase

The model is internally consistent but describes a system that cannot exist: a process whose reactant and product are the same species, a reservoir with no tracked isotope taking part in a fractionating process, a stopping condition that is already satisfied at the initial state.

IG215 — mixing fractions do not sum to one

error · validation phase

The source fractions of a mixing process must sum to one within 1e-6.

When a fraction is a parameter, the check runs after parameter evaluation. It is deferred entirely when the parameter is a FIT target, since its value is not known before calibration.

Execution

Raised by an engine while a model runs. A front end never sees these.

IG301 — solver failed to converge

error · execution phase

The numerical solver did not reach its tolerance within the allowed iterations.

The diagnostic reports the simulation time at which convergence failed, which is usually enough to locate the stiff process.

IG302 — numerical instability

error · execution phase

A state variable became non-finite during integration.

The usual cause is a rate constant far larger than the inverse of the timestep. Reducing `step` in the MODEL block, or letting the engine choose an adaptive step, resolves most occurrences.

IG303 — division by zero during evaluation

error · execution phase

An expression divided by a quantity that evaluated to zero at run time.

Temperature-dependent fractionation laws written against T are the common case, when the enclosing scope declares no temperature and the default resolves to zero rather than to a physical value.

IG304 — negative remaining fraction

error · execution phase

A reactant pool went below zero.

This is a mass balance failure rather than a modelling choice, and the engine stops instead of clamping, because a clamped pool silently breaks the isotopic balance downstream.

IG305 — reaction progress outside 0 to 1

error · execution phase

An `extent` evaluated to a value that is not a fraction of a reactant.

A literal is bounded by the validator, which can read it. An expression cannot be judged before it is evaluated, so the check happens while the model runs, and it happens rather than being skipped: a fraction above one leaves a negative amount behind, and the closed form of a distillation then takes the logarithm of a negative number. A composition arrives, it is not a number, and nothing says which of the two was at fault.

The common source is a progress computed from a backend, where the denominator was not the total the numerator was measured against.

IG306 — a statement the chosen progress does not read

warning · execution phase

A process states an `extent` and the model advances by time, or the reverse.

The two are alternative ways of driving a model, not layers of one. Under `progress time` an engine integrates a rate law and never consults an extent; under `progress extent` it never advances a clock. The statement is therefore not wrong, it is unread, which is worse than wrong because the model looks as though it says something it does not.

It is a warning rather than an error because the model still has a defined meaning: the unread statement changes nothing.

Backend

Raised when a chemistry engine is required, missing, or refuses its input.

IG401 — required backend unavailable

error · backend phase

The model requires a backend this installation does not provide.

An implementation must not substitute an approximation of its own for a missing backend. A PHREEQC block without PHREEQC is an error, not an invitation to guess the speciation.

IG402 — backend reported a failure

error · backend phase

The backend ran and returned an error. Its own message is included verbatim in the diagnostic, since it is generally more precise than anything IGL could infer from the failure.

IG403 — backend communication timeout

error · backend phase

The backend did not answer within the configured timeout.

IG404 — a backend series read outside what it recorded

error · backend phase

A parameter exported under `mode series` was read at an instant the backend never reported.

The engine holds the last recorded state until the next one, which is true: it is the last thing the chemistry said. It does not hold the first state backwards in time, because the backend said nothing about that instant and a value invented there would be indistinguishable from one it computed.

The usual cause is a model whose clock starts before the backend's, or a SELECTED_OUTPUT that does not record the initial solution.