scrml.dev v0.7.1
Reference › Errors

E-STRUCTURAL-ELEMENT-MISPLACED

A scrml-defined structural element appears outside the locus it belongs to.

Error Compile-time (BS / PA stage) SPEC §4.15 (normative)

What it means

scrml defines a small set of structural elements that look like HTML tags but are scrml-language constructs: <engine>, <match>, <errors>, <onTransition>, <onTimeout>, <onIdle>, <page>. Each has a strict owning locus — the place it's grammatical to use it. Outside that locus, the compiler emits E-STRUCTURAL-ELEMENT-MISPLACED.

Owning loci

Element Grammatical only as… SPEC
<onTransition> Child of <engine> §51.0.H
<onTimeout> Child of an engine state-child §51.0.M
<onIdle> Child of <engine> (sibling of state-children; one per engine) §51.0.R
(specific code: E-IDLE-MISPLACED)
<errors> Anywhere with a parent context that supports validity-surface rendering §55.8
<page> Child of <program> in MPA mode §40.8
<engine> / <match> File scope or inside an engine's composite state-child (engines may nest per §51.0.K) §51 / §18.0

Minimal reproducer

<onTransition> at file scope, outside any engine:

<onTransition from=.A to=.B>
  ${ log("transitioned") }
</onTransition>

E-STRUCTURAL-ELEMENT-MISPLACED fires at the opener — <onTransition> outside <engine>.

<onTimeout> at file scope:

<onTimeout after=5s to=.Done/>

Same error — <onTimeout> outside an engine state-child.

How to fix

  1. Move the element inside its owning locus. For <onTransition>, wrap it in an engine declaration. For <onTimeout>, place it inside a state-child body.
  2. If the element shouldn't exist, delete it. Misplacement sometimes reveals dead code that was moved away from its engine during refactoring.
  3. Check the rules-inert siblings. Inside a <match> block (§18.0.2), <onTransition> fires the more specific E-MATCH-ONTRANSITION-FORBIDDEN instead. Promote the match to an engine if you need transition effects.

Specific misplacement codes

Some elements have a dedicated misplacement code with sharper messaging:

When a more specific code applies, the compiler fires that one instead of the generic E-STRUCTURAL-ELEMENT-MISPLACED.

Related

  • <engine> — the canonical owner of onTransition / onTimeout / onIdle.
  • <match> — rules-inert; effect=/onTransition forbidden here. Promote to engine instead.
  • <errors> — renders the auto-synthesized validity surface; needs a parent context with validators.
  • E-NAME-COLLIDES-RESERVED — companion error when a user component name collides with a reserved structural-element identifier.

Specification

Normative text: SPEC §4.15 (structural-element registry), §24.4 (HTML-aware element classification), per-element owning sections (§51.0.H / §51.0.M / §51.0.R / §55.8 / §40.8), §34 catalog row. Spec lives at compiler/SPEC.md .