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.
| Code | Severity | Phase | Summary |
| IG001 | error | syntax | unexpected token |
| IG002 | error | syntax | unterminated string |
| IG003 | error | syntax | unknown block header |
| IG004 | error | syntax | statement is not indented |
| IG005 | error | syntax | block belongs to an unsupported profile |
| IG006 | error | syntax | non-ascii character outside an accepted position |
| IG007 | error | syntax | malformed expression |
| IG008 | error | syntax | unknown or malformed unit |
| IG009 | error | syntax | named block is missing its identifier |
| IG010 | warning | syntax | block identifier does not begin with an uppercase letter |
| IG011 | warning | syntax | a block this implementation does not honour |
| IG101 | error | semantic | reference to an undeclared entity |
| IG102 | error | semantic | duplicate name in the global namespace |
| IG103 | error | semantic | malformed or unknown isotope ratio |
| IG104 | error | semantic | mismatched element symbols across a ratio |
| IG105 | error | semantic | duplicate of a block that must be unique |
| IG106 | error | semantic | no reference standard resolvable for a ratio |
| IG107 | error | semantic | unresolved symbol in an expression |
| IG108 | warning | semantic | local symbol shadows a global one |
| IG109 | error | semantic | ill-formed qualified name |
| IG110 | error | semantic | assignment to a read-only symbol |
| IG201 | error | validation | value outside the admissible range |
| IG202 | error | validation | value does not match the expected type |
| IG204 | error | validation | unit incompatible with the expected dimension |
| IG205 | error | validation | unit omitted where several are admissible |
| IG210 | error | validation | unknown property for this block type |
| IG211 | error | validation | required property missing |
| IG212 | warning | validation | recommended property absent |
| IG213 | error | validation | mutually exclusive properties both present |
| IG214 | error | validation | physically inadmissible configuration |
| IG215 | error | validation | mixing fractions do not sum to one |
| IG301 | error | execution | solver failed to converge |
| IG302 | error | execution | numerical instability |
| IG303 | error | execution | division by zero during evaluation |
| IG304 | error | execution | negative remaining fraction |
| IG305 | error | execution | reaction progress outside 0 to 1 |
| IG306 | warning | execution | a statement the chosen progress does not read |
| IG401 | error | backend | required backend unavailable |
| IG402 | error | backend | backend reported a failure |
| IG403 | error | backend | backend communication timeout |
| IG404 | error | backend | a 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.
Top of page