E-IDLE-DUPLICATE
An
<engine>
declares more than one
<onIdle>
element. One per engine maximum.
What it means
<onIdle>
is the engine-wide event-timeout watchdog. Per §51.0.R, every
engine has AT MOST ONE watchdog — multiple onIdle
declarations would race for the same runtime timer slot
(composite key
<varName>::__idle
in
_scrml_machine_timers).
The compiler rejects multiple at compile time.
Minimal reproducer
type Phase:enum = { Active, Idle, Away }
<engine for=Phase initial=.Active>
<Active rule=(.Idle | .Away) />
<Idle rule=.Active />
<Away rule=.Active />
<onIdle after=5m to=.Idle/>
<onIdle after=30m to=.Away/>
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// E-IDLE-DUPLICATE: second <onIdle> in the same engine.
// One per engine maximum.
</>
How to fix
-
Pick the right single watchdog.
If the intent is "idle for 5 minutes →
.Idle; further idle for 30 minutes total →.Away," model the cascade as an<onIdle>that transitions to.Idle, plus an <onTimeout> on the.Idlestate-child that transitions to.Awayafter another 25 minutes. -
Use per-state <onTimeout> for state-scoped timing.
If two timers reflect different states' timing needs
rather than engine-wide silence, they belong on each
state-child as
<onTimeout>instances, NOT as multiple<onIdle>.
Cascade pattern (recommended)
<engine for=Phase initial=.Active>
<Active rule=(.Idle | .Away) />
<Idle rule=(.Active | .Away)>
<onTimeout after=25m to=.Away/>
</>
<Away rule=.Active />
<onIdle after=5m to=.Idle/>
</>
Composes cleanly: the engine-wide
<onIdle>
fires after 5m silence → moves to
.Idle;
entering
.Idle
arms the per-state
<onTimeout>
for another 25m → moves to
.Away
at the 30m total mark.
Related
- <onIdle> — element reference. Engine-wide watchdog.
- <onTimeout> — per-state timer; the composition partner for cascade patterns.
- E-IDLE-MISPLACED — sibling error when <onIdle> sits inside a state-child body.
- E-IDLE-INVALID-VARIANT — sibling error when to= references a non-enum variant.
Specification
Normative text: SPEC §51.0.R (one-per-engine rule + runtime composite-key encoding), §34 catalog row. Spec lives at compiler/SPEC.md .