# Reference — Limitations ![code-ref](https://img.shields.io/badge/code--ref-a3583a3-blue) > [!NOTE] > Pending full node review (2026-05). What `settler` does not do, current rough edges, and open questions. Open items live in `.agents/improvements/IMPROVEMENTS_BACKLOG.md` in the superproject. --- ## When you would not use this node | Scenario | Use instead | |:---|:---| | Primary sedimentation upstream of biological treatment | The species 7–12 zeroing in the effluent stream is wrong for primary sludge (the soluble / particulate split is different). Model as a separate node. | | Generic mass-balance transform | The 13-species ASM3 concentration vector is hard-coded; `Cs[12]` (`X_TS`) is the only species the split is keyed off. Not a fit for arbitrary stream-splitting. | | Single-tank SBR with no separation stage | The 3-stream output expects a downstream consumer that routes by `payload.inlet`. A direct reactor → reactor wire is lighter. | | A reactor — you want to model biological transformation, not separation | `reactor` (settler is a passive separator, not a biological process). | | A return-pump itself — you want to model the pump's behaviour | `rotatingMachine` (settler reads the pump's measured flow but does not control it). | --- ## Known limitations ### Example flows are stub level The three shipped flows (`basic.flow.json`, `integration.flow.json`, `edge.flow.json`) are 4-node skeletons (tab + node + inject + debug). They prove the node loads in Node-RED but do not exercise the reactor → settler → pump chain, do not drive `data.influent` with a valid payload, and do not have a dashboard tier. Production-grade examples are TODO — see [Reference — Examples — TODO](Reference-Examples#todo--production-grade-example-set). ### Editor colour drift `settler.html` declares `color: '#e4a363'` (orange). The S88 Unit level requires `#50a8d9` (blue). The placement-rule registry (`.claude/rules/node-red-flow-layout.md` §14) already maps `settler` to the `UN` lane regardless of editor colour, so demos lay out correctly; the cosmetic mismatch is tracked in §16 of the same rule and is on the colour-cleanup list. The wiki diagrams use the correct blue. ### Single-reactor upstream slot `this.upstreamReactor` is a single slot. Registering a second `reactor` child with `positionVsParent='upstream'` silently overwrites the first — the listener on the previous reactor's `emitter` is not detached, so it keeps firing into a settler that will pull effluent from the new reactor instead. Tracked. ### `X_TS` index is hard-coded The mass balance uses `Cs_in[12]` (the ASM3 `X_TS` lumped solids species) as the surrogate for total suspended solids. Any change to the species ordering in the upstream reactor breaks settler. The coupling is not documented in the schema — it lives only in the `getEffluent` math and the `_updateMeasurement` switch case for `quantity (tss)`. Tracked. ### No flow-balance warning When influent solids exceed the target return concentration (`Cs_in[12] > C_TS`), `F_s` is clamped to `F_in` and clarified effluent drops to zero. This is mathematically correct but masks an upstream problem (overloaded reactor, miscalibrated `C_TS` setpoint). The clamp fires silently — no warn, no badge change beyond the eventual `F_in <= 0` idle state. Operator must monitor `F_eff` directly. Tracked. ### `quantity (tss)` measurement passes through but doesn't validate `_connectMeasurement` re-emits every measurement type, but `_updateMeasurement` only acts on `quantity (tss)`. Other types log an `error` (`Type '' not recognized for measured update.`) but the re-emit already happened — the parent of settler still sees the value. Whether this is desired (settler acts as telemetry pass-through) or a contract gap is unresolved. > [!NOTE] > Pending full node review (2026-05). Open question: should `_connectMeasurement` filter by asset-type at register time and reject non-`quantity (tss)` children, or continue accepting everything as pass-through telemetry? ### No output manifest / no degraded-state coverage Per the platform output-coverage rule (`.claude/rules/output-coverage.md`), every node needs a `test/_output-manifest.md` enumerating every Port 0 / 1 / 2 key and a `test/basic/output-*.test.js` exercising each one in both populated **and** degraded states. Settler has neither. The most likely degraded-state crash points: - Port 0 emitted before any reactor `stateChange` — `F_in = 0`, `Cs_in = [0...]`, the three envelopes carry zero flow but valid (zero) `C` arrays. Should not crash a downstream consumer, but un-tested. - Port 0 with `returnPump` registered but no flow measurement landed yet — `returnPump.measurements.type('flow').variant('measured').position('atEquipment').getCurrentValue()` returns `undefined` → `Math.min(undefined, F_s) = NaN`. `F_sr` becomes `NaN` → both `inlet=1` and `inlet=2` carry `NaN` flow. Tracked. TODO before trial-readiness: add the manifest, tests, and `null`-flow-measurement handling. ### `reactor.getEffluent` shape coupling `_connectReactor` does `Array.isArray(raw) ? raw[0] : raw` to absorb both the older single-envelope shape and the newer 3-stream array shape of `reactor.getEffluent`. The 2026-03-02 fix is the only thing keeping the older shape alive in production. If `reactor.getEffluent` ever returns a 3-stream array and settler should consume `inlet=0` specifically, the current `raw[0]` selector works by accident — it picks the first envelope regardless of inlet number. Open question whether to make the selection inlet-aware. ### Stateful telemetry — no decay / no TTL The MeasurementContainer holds the last-known value of every re-emitted measurement forever. If a child stops publishing, the stale value persists on Port 1 indefinitely. There is no TTL, no `data.clear-measurement` topic, and no health flag like `rotatingMachine`'s `predictionQuality`. Open question. --- ## Open questions (tracked) | Question | Where it lives | |:---|:---| | Filter `_connectMeasurement` by asset-type at register time? | Internal — not yet ticketed | | Multi-reactor upstream support — teardown ordering, listener detach | Internal | | Flow-balance warning when `F_s` clamp fires | Internal | | Inlet-aware selection in `_connectReactor` shape handling | Internal | | Measurement TTL / staleness flag | Internal | | Production-grade example flows (Tier 1 / 2 / 3) | `.agents/improvements/IMPROVEMENTS_BACKLOG.md` | | Output manifest + degraded-state tests | `.claude/rules/output-coverage.md` (platform-wide rule) | | Editor colour cleanup (`#e4a363` → `#50a8d9`) | `.claude/rules/node-red-flow-layout.md` §16 | --- ## Migration notes > [!NOTE] > Pending full node review (2026-05). No structural migrations have been performed on settler since the AssetResolver refactor of rotatingMachine; the notes below document the one historical fix on record. ### From pre-2026-03-02 `_connectReactor` Before 2026-03-02 `_connectReactor` assumed `reactor.getEffluent` always returned an array, and indexed `[0]` unconditionally. After the reactor refactor, `getEffluent` returns a single envelope — pre-fix settler would crash with `Cannot read properties of undefined (reading 'payload')`. The fix: ```js const raw = this.upstreamReactor.getEffluent; const effluent = Array.isArray(raw) ? raw[0] : raw; ``` If you maintain a fork of settler from before that date, port this guard. ### From topic-aliased payloads Both `influent` and `setInfluent` are accepted as aliases for `data.influent`. A one-time deprecation warning fires the first time each alias is seen. Tracked for removal; use the canonical `data.influent` in new flows. --- ## Related pages | Page | Why | |:---|:---| | [Home](Home) | Intuitive overview | | [Reference — Contracts](Reference-Contracts) | Topic + config + child filters | | [Reference — Architecture](Reference-Architecture) | Code map, reactor ↔ settler wiring, mass-balance math | | [Reference — Examples](Reference-Examples) | Shipped flows + the TODO list for production-grade demos | | [reactor — Limitations](https://gitea.wbd-rd.nl/RnD/reactor/wiki/Reference-Limitations) | The upstream parent — effluent shape contract | | [EVOLV — output-coverage rule](https://gitea.wbd-rd.nl/RnD/EVOLV/src/branch/development/.claude/rules/output-coverage.md) | Platform-wide output-coverage requirement |