Validation Categories Reference
Every validation rule in epanetparser is assigned a category that classifies
the type of check it performs. Categories appear in JSON/TOON output, console
reports (with --verbose), and the epanetparser-plugins show command.
This reference documents all eight categories, their associated EPANET error
codes (where applicable), and example rules from the epanet_core ruleset.
Category Overview
Category |
EPANET Codes |
Severity |
Description |
|---|---|---|---|
219, 220, 222, 223, 224, 233, 234 |
ERROR / WARNING |
Network structure: connectivity, loops, valve placement, dead ends |
|
202, 208, 209, 211, 213, 225, 227 |
ERROR / WARNING |
Component field values: ranges, required fields, numeric validity |
|
227, 230 |
ERROR / WARNING |
Curve well-formedness: points, types, semantics, monotonicity |
|
207, 221 |
ERROR |
Control logic: rule clauses, simple/rule controls, circular refs |
|
203, 204, 205, 206, 212, 216 |
ERROR |
Cross-component references: names, curves, patterns, pumps |
|
200, 201, 210, 214, 215, 217, 218, 226, 228, 229, 231, 232 |
ERROR / WARNING |
Simulation options: time, hydraulic, quality, energy, reactions |
|
235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246 |
ERROR / WARNING |
Energy/pumping: efficiency curves, prices, patterns, global settings |
|
(judgment) |
WARNING |
Heuristics: valve authority, tank turnover, demand patterns, duplicates |
Topology
EPANET error codes: 219, 220, 222, 223, 224, 233, 234
Checks the physical structure and connectivity of the network. These are structural constraints that EPANET itself enforces.
Example rules (epanet_core):
Rule Code |
Severity |
Description |
|---|---|---|
|
ERROR |
Valves cannot connect to Tank or Reservoir nodes (EPANET 219) |
|
ERROR |
Valves cannot connect directly to other valves (EPANET 220) |
|
ERROR |
A link must not connect a node to itself (EPANET 222) |
|
ERROR |
Network must have at least one tank or reservoir (EPANET 224) |
|
ERROR |
All demand nodes must be hydraulically connected (EPANET 233/234) |
|
ERROR |
Multiple links connecting the same node pair (duplicate detection) |
|
WARNING |
Junctions with degree=1 and no demand/emitter are suspicious |
|
ERROR |
Junctions connected only via valves cannot be pressure-driven |
|
WARNING |
Multiple nodes with identical coordinates |
|
WARNING |
Nodes without coordinates cannot be displayed on a map |
Parameter
EPANET error codes: 202, 208, 209, 211, 213, 225, 227
Validates individual component field values: required fields present, numeric types, value ranges, and logical constraints (e.g., tank level ordering).
Example rules (epanet_core):
Rule Code |
Severity |
Description |
|---|---|---|
|
ERROR |
A node must have a name |
|
ERROR |
Junctions must have elevation (EPANET 209) |
|
ERROR |
Reservoirs must have base_head (EPANET 209) |
|
ERROR |
Tanks must have diameter (EPANET 225) |
|
ERROR |
Tank levels must satisfy min ≤ init ≤ max (EPANET 225) |
|
ERROR |
Tank min_level, init_level, max_level ≥ 0 (EPANET 225) |
|
ERROR |
Tank diameter must be > 0 (EPANET 225) |
|
ERROR |
Tank min_vol ≥ 0 (EPANET 225) |
|
ERROR |
Junction base demand ≥ 0 (EPANET 209) |
|
ERROR |
Junction emitter coefficient ≥ 0 (EPANET 209) |
|
ERROR |
Pipe length must be > 0 (EPANET 209) |
|
ERROR |
Pipe diameter must be > 0 (EPANET 209) |
|
ERROR |
Pipe roughness ≥ 0 (EPANET 209) |
|
ERROR |
Pump power ≥ 0 (EPANET 209) |
|
ERROR |
Valve setting ≥ 0 (EPANET 209) |
|
WARNING |
Tank max_level should not exceed diameter for cylindrical tanks |
|
WARNING |
Junction with zero demand and no emitter may be unnecessary |
Curve
EPANET error codes: 227, 230
Validates curve well-formedness: minimum points, sorted x-values, no duplicate x-values, and semantic correctness for pump/efficiency/headloss/volume curves.
Example rules (epanet_core):
Rule Code |
Severity |
Description |
|---|---|---|
|
ERROR |
A curve must have a name |
|
ERROR |
Curve type must be HEAD, PUMP, EFFICIENCY, or VOLUME |
|
ERROR |
A curve must have at least one point |
|
ERROR |
A curve must have at least 2 points for interpolation |
|
ERROR |
Curve x-values must be strictly increasing |
|
ERROR |
Curve x-values must be unique (no duplicate x) |
|
ERROR |
Pump curve y-values (head) must be ≥ 0 |
|
ERROR |
Efficiency curve y-values must be in [0, 100] |
|
ERROR |
Headloss curve y-values must be ≥ 0 |
|
ERROR |
Volume curve y-values must be strictly increasing |
Control
EPANET error codes: 207, 221
Validates control logic: rule control clause structure, simple control syntax, and circular dependency detection.
Example rules (epanet_core):
Rule Code |
Severity |
Description |
|---|---|---|
|
ERROR |
Rule control IF/THEN/ELSE clauses must be well-formed |
|
ERROR |
Simple control must have valid link/status/setting |
|
ERROR |
Rule controls must not have circular dependencies |
|
ERROR |
Control must reference an existing link |
|
ERROR |
Control condition must reference an existing node |
|
WARNING |
Control references a link not in the network |
Network
EPANET error codes: 203, 204, 205, 206, 212, 216
Cross-component reference resolution: ensuring every name used in one component exists in the appropriate collection.
Example rules (epanet_core):
Rule Code |
Severity |
Description |
|---|---|---|
|
ERROR |
Link endpoints must reference existing nodes (EPANET 203) |
|
ERROR |
Pump/efficiency/headloss/volume curves must exist (EPANET 204) |
|
ERROR |
Demand/head patterns must exist (EPANET 205) |
|
ERROR |
Source node/pattern must exist (EPANET 206) |
|
ERROR |
Control link must exist (EPANET 212) |
|
ERROR |
Quality trace_node must reference existing node (EPANET 216) |
|
ERROR |
Energy section pump references must exist |
|
ERROR |
Component names unique within collection |
|
ERROR |
Network must have at least one node |
|
ERROR |
Network must have at least one link |
|
ERROR |
Network must have a name (from [TITLE]) |
Option
EPANET error codes: 200, 201, 210, 214, 215, 217, 218, 226, 228, 229, 231, 232
Validates simulation options across all categories: time, hydraulic, quality, energy, and reaction options.
Example rules (epanet_core):
Rule Code |
Severity |
Description |
|---|---|---|
|
ERROR |
Time options section must be present |
|
ERROR |
Duration must be > 0 |
|
ERROR |
Hydraulic timestep must be > 0 |
|
ERROR |
Quality timestep must be > 0 |
|
ERROR |
Pattern timestep must be > 0 |
|
ERROR |
Pattern timestep must divide hydraulic timestep |
|
ERROR |
Report timestep must be > 0 |
|
ERROR |
Start clocktime must be valid HH:MM format |
|
ERROR |
Hydraulic options section must be present |
|
ERROR |
Headloss formula must be H-W, D-W, or C-M |
|
ERROR |
Demand model must be DD or PDA |
|
ERROR |
Minimum pressure (PDA) must be ≥ 0 |
|
ERROR |
Required pressure (PDA) must be > 0 |
|
ERROR |
Pressure exponent (PDA) must be in [0, 1] |
|
ERROR |
Quality options section must be present |
|
ERROR |
Quality type must be NONE, CHEMICAL, AGE, or TRACE |
|
ERROR |
Trace node must exist when quality type is TRACE |
|
ERROR |
Reaction options section must be present |
|
ERROR |
Bulk reaction order must be ≥ 0 |
|
ERROR |
Wall reaction order must be ≥ 0 |
|
ERROR |
Tank reaction order must be ≥ 0 |
|
ERROR |
Global bulk coefficient must be valid |
|
ERROR |
Global wall coefficient must be valid |
|
ERROR |
Limiting concentration must be ≥ 0 |
Energy
EPANET error codes: 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246
Validates energy and pumping options: efficiency curves, pump efficiency ranges, global efficiency, price patterns, and pump-specific settings.
Example rules (epanet_core):
Rule Code |
Severity |
Description |
|---|---|---|
|
ERROR |
Energy options section must be present if pumps exist |
|
ERROR |
Pump efficiency curve must be EFFICIENCY type |
|
ERROR |
Pump efficiency curve values must be in [0, 100] |
|
ERROR |
Global efficiency (when no curve) must be in (0, 100] |
|
ERROR |
Energy price pattern must reference existing pattern |
|
ERROR |
Global energy pattern must exist |
|
ERROR |
Per-pump price patterns must exist |
|
ERROR |
Per-pump energy patterns must exist |
|
ERROR |
Per-pump efficiency curves must be EFFICIENCY type |
|
WARNING |
Pump has no efficiency curve and no global efficiency |
|
WARNING |
Tank volume / avg daily demand > 7 days (low turnover) |
|
WARNING |
Tank volume / avg daily demand < 0.5 days (high turnover) |
|
WARNING |
PRV/PSV authority < 0.25 indicates poor control |
Engineering
EPANET error codes: (judgment-based, not in EPANET spec)
Heuristic warnings based on engineering best practices. These do not correspond to EPANET error codes but flag configurations that are legal yet questionable.
Example rules (epanet_core):
Rule Code |
Severity |
Description |
|---|---|---|
|
WARNING |
Demand pattern all 1.0 (no diurnal variation) |
|
WARNING |
Junction has demand but no pattern assigned |
|
WARNING |
Multiple quality sources at same node |
|
WARNING |
Reservoir has no head pattern (constant head) |
|
WARNING |
Junction with zero demand and no emitter may be unnecessary |
|
WARNING |
Tank max_level should not exceed diameter |
|
WARNING |
Dead-end junctions with no demand/emitter |
|
WARNING |
Multiple nodes with identical coordinates |
|
WARNING |
Nodes without coordinates cannot be displayed |
MILP Custom Ruleset Categories
The milp custom ruleset adds application-specific constraints:
Rule Code |
Category |
Description |
|---|---|---|
|
Option |
Hydraulic timestep must match MILP timestep (3600s) |
|
Option |
Duration must be multiple of MILP timestep |
|
Option |
Pattern length must be 24 hours |
|
Parameter |
Units must be LPS (not GPM) |
|
Option |
Headloss must be Hazen-Williams |
|
Option |
Demand model must be DD (not PDA) |
|
Option |
Quality must be NONE |
|
Option |
Reactions must be disabled |
|
Topology |
Valve links not supported |
|
Control |
Check valves not supported |
|
Control |
General purpose valves not supported |
|
Parameter |
Emitters not supported |
|
Control |
Controls not supported |
|
Network |
Sources not supported |
|
Curve |
Only HEAD pump curves supported |
|
Engineering |
Various MILP-specific warnings |
Using Categories in Custom Rules
When writing custom rules, include the classification field in the docstring:
from epanetparser.core.validation import rule
@rule("WNTREPANETLink", code="E_MY_CUSTOM_RULE", attribute="length")
def rule_my_custom_check(link) -> None:
"""Pipe length must not exceed 1000m for this application.
classification : Parameter
fix : Reduce pipe length or split into shorter segments.
"""
length = link.data.get("length", 0)
assert length <= 1000, f"Pipe length {length}m exceeds 1000m limit"
The category must be one of the eight standard categories listed above. This ensures consistent reporting and enables filtering by category in downstream tooling.
See Also
Rules, Warnings, and Rule Sets — How to write rules and rule sets
Basic Usage — CLI options for filtering and displaying categories
The epanetparser Library — Python API for accessing issue categories