# Errors and validation

rbed reports a mistake as early as it can, most of them when the Detector is built, and always with an exception whose message names what is wrong.

## A warm room

A room's temperature is reported once a second; it is 28 °C from 10 to 29 s and 22 °C otherwise. `Warm` holds while the average of the last few Samples is above 25 °C, for a duration; `Hot` holds while a `Warm` Event runs and the temperature itself is above 27 °C.

Parameters (in the page address as ?window=…):

- Average over (`window`): 1 to 12 Samples in steps of 1, default 5
- Retention Limit (`retention`): 0 to 10 entries in steps of 1, default 10
- Warm for (`duration`): -1 to 5 s in steps of 1, default 2
- Rules added (`order`): 0 for Warm, then Hot (default), 1 for Hot, then Warm

The site cannot run the default parameters: (JavaScript) TypeError: Cannot read properties of undefined (reading 'length')

Java source at the default parameters:

```java
import static io.github.romanhaendler.rbed.Conditions.*;

import io.github.romanhaendler.rbed.*;
import java.time.Duration;
import java.util.Map;

Channel temp = Channel.named("temp");

Rule warm = Rule.named("Warm")
    .when(temp.averageOverSamples(5).above(25))
    .forDuration(Duration.ofSeconds(2));
Rule hot = Rule.named("Hot").when(during(warm).and(temp.above(27)));
Detector detector = Detector.builder()
    .retentionLimit(10)
    .rules(warm, hot)
    .build();

for (int s = 0; s <= 40; s++) {   // one Sample a second
  detector.push(s * 1_000L, Map.of(temp, s >= 10 && s < 30 ? 28.0 : 22.0));
}
detector.close();
```

At the defaults, the average over 5 Samples rises above 25 °C at 12 s, the third warm Sample, and `Warm` is Confirmed two seconds later; `Hot` starts with that confirmation and Ends at 30 s, the first cool Sample.

### Things to try

- Raise *Average over* above the *Retention Limit*, the most entries one window may keep (1,000,000 by default, 10 here). An average over n Samples must keep n values, so `build()` rejects an n above the Retention Limit and says how to fix it: raise the limit with `Detector.builder().retentionLimit(...)`.
- Set the *Retention Limit* to 0: `retentionLimit` itself rejects a limit below one.
- Set *Warm for* to −1 s: `forDuration` rejects a negative duration as soon as the Rule is written, before any Detector exists.
- Add `Hot` before `Warm`. A Rule may only refer to Rules added before it, since Rules are evaluated in the order they are added, so `build()` rejects `Hot`.

## What else is rejected

- An empty Rule or Channel name, a Rule without `when`, two Rules with the same name.
- `forDuration` or [`forSamples`](https://romanhaendler.github.io/rbed/event-lifecycle/#durations-forduration-and-forsamples) before any `when` or `endWhen`; negative durations, `forSamples(0)`, `between` with its low above its high.
- A sampling rate outside (0, 1000] Hz; a History Event that has not Ended, or whose name matches no Rule; one Channel name used both as a Pulse Channel and as an ordinary one.
- While running: a timestamp not after the previous Sample or advance (or, with History, not after its latest end); a NaN, infinite or null value (the Sample is then ignored); pushing after `close()`; the wrong `push` for the sampling mode.
- A Rule referring to itself, to a Rule added after it, or to one not added at all (`build()`).
- Reading the Aggregates of a Channel the Rule does not aggregate.

The [Restarts: History](https://romanhaendler.github.io/rbed/history/) and [Silent sensors](https://romanhaendler.github.io/rbed/silent-sensors/) pages show restarts and time advances that stay within these rules. What the Retention Limit is, and what happens when a window reaches it, is on [Memory and the Retention Limit](https://romanhaendler.github.io/rbed/memory/).

## Reference

- [Errors and validation](https://github.com/romanhaendler/rbed#errors-and-validation) in the README, the canonical text, with the method that reports each mistake

Methods used: [`Channel.named`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Channel.html#named%28java.lang.String%29), [`Rule.named`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Rule.html#named%28java.lang.String%29), [`Rule.when`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Rule.html#when%28io.github.romanhaendler.rbed.Condition%29), [`ChannelExpression.averageOverSamples`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/ChannelExpression.html#averageOverSamples%28int%29), [`Expression.above`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Expression.html#above%28double%29), [`Rule.forDuration`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Rule.html#forDuration%28java.time.Duration%29), [`Conditions.during`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Conditions.html#during%28io.github.romanhaendler.rbed.Rule%29), [`Condition.and`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Condition.html#and%28io.github.romanhaendler.rbed.Condition%29), [`Detector.builder`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Detector.html#builder%28%29), [`Detector.Builder.retentionLimit`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Detector.Builder.html#retentionLimit%28int%29), [`Detector.Builder.rules`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Detector.Builder.html#rules%28io.github.romanhaendler.rbed.Rule...%29), [`Detector.Builder.build`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Detector.Builder.html#build%28%29), [`Detector.push`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Detector.html#push%28long,java.util.Map%29), [`Detector.close`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Detector.html#close%28%29).
