Docs
/
Reference
Diagnostics
Every problem the compiler, the analyzer or the runtime reports has a code. layr explain <code> prints the same explanation in your terminal, and your editor shows it on hover.
L0: Syntax
L0001: Unexpected character
error. The file contains a character that cannot start any LAYR token.
L0002: Unterminated string
error. A string was opened with ' or " but not closed on the same line.
L0003: Unterminated comment
error. A /* comment has no closing */.
L0004: Unterminated block
error. A { TypeScript block has no matching }.
L0005: Unmatched brace
error. A } appears without an opening {.
L0010: Expected token
error. The parser expected a specific token here, usually a closing ).
L0011: Unexpected token
error. This token cannot start an item. Items are modifiers (.config(...)), props (key: value), declarations or values.
L0012: Missing separator
error. Commas between items are optional, but an item cannot be followed on the same line by an operator that does not continue it. Put the next item on its own line, or add a ,.
Wrong:
Row(Text('a') ] Text('b'))Right:
Row(Text('a') Text('b'))L0013: Invalid import
error. Imports follow TypeScript syntax: import { a } from 'pkg', import X from './x.layr'.
L0014: Expected a value
error. A value (number, string, colour, name or call) was expected here.
L1: Names and types
L1001: Unknown widget
error. No core widget, project widget or addon widget has this name. Check the spelling or import it.
L1002: Unknown config key
error. This widget has no such config key. The message lists the closest keys.
Wrong:
Container(.config(widht: 200))Right:
Container(.config(w: 200))L1003: Wrong value type
error. The value does not match the key's type (for example a colour where a length is expected).
L1004: Unknown value
error. This identifier is not one of the values the key accepts.
L1005: Unknown name
error. The name is not a declared var/const/bind, param, Function, import or object id in scope.
L1006: Unknown modifier
error. This modifier does not exist on this widget or construct.
L1007: Wrong slot
error. The object was given to a slot that does not accept it (for example several objects in a single .obj).
L1008: Missing required value
error. A required param or slot was not provided.
L1009: Duplicate id
error. Two objects in the same Page or Widget share an .id. Ids must be unique per definition.
L1010: Duplicate declaration
error. The name is already declared in this scope.
L1011: Non-canonical spelling
info. An alias or non-canonical form was used. layr format rewrites it to the canonical form.
L1012: Duplicate config key
error. The same key is set twice in one .config.
L1013: Invalid Page
error. A Page needs .name(...) and exactly one root object (usually a Scaffold).
L1014: Invalid Widget
error. A Widget needs .name(...) and one .obj(...) root.
L1015: Unknown frame
error. .at(frame, ...) names a frame that the active DesignScale does not define.
L1016: Unused declaration
warning. The declaration is never read.
L2: Layout
L2001: fill on an unbounded axis
error. fill shares remaining space, but a scrolling axis has no end, so there is nothing to share. Give the object a length or hug, or bound the scroll area.
Wrong:
Scroll(Column(Container(.config(h: fill))))Right:
Scroll(Column(Container(.config(h: 400))))L2003: Invisible box
warning. A hug Container with no child is 0×0, so its paint is never visible. Give it a size.
L2101: Overflow cannot adapt
warning. The content cannot fit and no adaptation applies (for example a fixed child larger than its fixed parent on both axes). It is clipped. Make a size flexible or set overflow explicitly.
L2102: Layout adapted
info. At some frame this Row wraps or stacks. The message says where. Set overflow to make the choice explicit.
L3: Export, Extract, Inject
L3101: Mutating a !mut feature
error. The target was declared !mut, which refuses every Export/Extract/Inject mutation. Remove !mut at the declaration or stop mutating it. Inject(.force …) inside access.force paths can override it.
Wrong:
Container(.id(card) .config(!mut color: red))
Inject(.into(Page.card) card.color = blue)Right:
Container(.id(card) .config(color: red))
Inject(.into(Page.card) card.color = blue)L3102: Conflicting injection order
error. Two Injects target the same feature with the same .exeOrder. Give them different orders so the result is unambiguous.
L3103: Unordered injections
warning. Two Injects without .exeOrder target the same feature. They apply in file/line order; add orders to make intent explicit.
L3104: Rendered features are read-only
error. pos and visible are measured from layout and cannot be injected or written. size is measured too, but an object with a size key of its own (a Text's font size, a box's size) takes writes and Injects there; reading size still gives the measurement.
L3105: Force outside access.force
error. Inject(.force …) is only allowed in files matched by access.force in layr.yaml (or everywhere with access.inject: open).
L3201: Layout cycle
error. An object's size depends on a rendered feature that depends on the object itself. Break the cycle.
L3202: Runtime layout cycle capped
warning. A dynamic rendered-feature dependency did not settle within two passes; the last value was kept.
L3203: Extract reads its own Inject
error. An Extract without .exeOrder reads the final value, after every Inject. An Inject that uses that value to change the same feature would read its own output. Give the Extract an order at or below the Inject's: it then reads the value under that Inject.
Wrong:
Extract(.from(Store.card) insets base = card.padding)
Inject(.into(Store.card) .exeOrder(0) card.padding = base * 2)Right:
Extract(.from(Store.card) .exeOrder(-1) insets base = card.padding)
Inject(.into(Store.card) .exeOrder(0) card.padding = base * 2)L3301: Unresolved lookup path
error. No object matches this lookup path. Paths descend by widget name (lowercase), slot name or id.
L3302: Private name
error. Names starting with _ are not reachable from outside their file.
L3303: Ambiguous lookup path
error. Several same-type siblings match this path segment. Pick one with a zero-based index: column.text(0), column.text(1), … or give the object an .id.
L3304: Index out of range
error. The (n) index in a lookup path is larger than the number of matching siblings.
L4: Design Scale
L4001: Invalid DesignScale
error. Frames need a design width, height and a non-overlapping from width.
L4002: Mixed units in interpolation
warning. Per-frame values interpolate only when all are design lengths; mixed units step at frame boundaries.
L5: Motion
L5101: Not animatable
warning. This key is not animatable; Animate changes it instantly.
L5102: Writing a bound feature
error. The feature is bound to an expression (for example w: xDim ?? 100). Write the source (xDim) instead, so there is one source of truth.
L6: Accessibility
L6001: Image without alternative
error. Images need alt text, or decorative: true if they carry no information.
L6002: Input without label
error. Inputs, Toggles, Selects and Sliders need a label for screen readers.
L6003: Button without accessible name
warning. Give the Button a label or text content.
L6101: Font range fails zoom
warning. A font's largest size is more than 2.5× its smallest across frames; browser zoom may not reach 200 % (WCAG 1.4.4).
L6102: Text too small
warning. Effective body text is below 12 px at some frame.
L7: Addons
L7001: Addon not installed
error. The import refers to an addon that is not in node_modules. Run layr add <addon>.
L7002: Addon incompatible
warning. The addon declares a LAYR range that does not include this version.
L7003: Invalid addon manifest
error. The addon's package.json layr field is missing or invalid.
L8: Assets
L8001: Single-resolution image
info. Large images should provide per-frame sources (src: (m: 'a.jpg', w: 'a@2x.jpg')).
L9: Interop
L9001: React-target only
info. Foreign React components and .react { } blocks run only on the React target. Set targets: [react] in layr.yaml to silence this.
L9002: Hooks outside .react
error. React hooks may only be called inside a .react { } block.