Skip to content

Latest commit

 

History

History
1868 lines (1169 loc) · 90.5 KB

File metadata and controls

1868 lines (1169 loc) · 90.5 KB

ArchLang error codes

Every diagnostic carries a stable code. Look one up with arch explain <CODE> (e.g. arch explain E_ROOM_SIZE). Errors abort rendering; warnings do not.

92 errors · 47 warnings

Code Severity Summary
E_ACC_PLACEMENT error accTitle/accDescr used outside the plan level.
E_ARC_RADIUS error Arc radius too small for its chord.
E_ARGCOUNT error Component called with the wrong number of arguments.
E_ARITY error Built-in function called with the wrong number of arguments.
E_ASSIGN_UNDEF error Assignment to an undeclared name.
E_ATTACH_POS_RANGE error Opening attachment position is out of range.
E_ATTACH_WALL_REF error Opening attached to an unknown or ambiguous wall.
E_CALL_DEPTH error Value-function call stack too deep.
E_COLUMN_SIZE error Column must have a positive size.
E_DIM_CURVE_REF error Invalid dim radius/dim diameter reference.
E_DIV_ZERO error Division or modulo by zero.
E_DOMAIN error Math domain error.
E_DOOR_KIND_CLAUSE error That clause is not available on this kind of door.
E_DOOR_KIND_CURVED error A non-hinged door kind cannot sit on a curved wall.
E_DOOR_OPEN_RANGE error open must be between 0 and 1.
E_DOOR_WIDTH error Door must have a positive width.
E_DOTTED_DECL error A dotted name cannot be declared.
E_DUP_ID error Duplicate element id.
E_DUP_INSTANCE error Duplicate place … as <name> instance name.
E_FENCE_CURVED error A fence cannot have a curved (arc) edge.
E_FURN_AGAINST error Invalid against wall fixture placement.
E_FURN_FLUSH error flush on a placement that touches no edge.
E_FURN_ROOM error Furniture placed in an unknown room.
E_FURN_ROTATE error Furniture rotation must be a quarter-turn.
E_FURN_SIZE error Furniture must have a positive size.
E_HEIGHT_RANGE error A height is outside the range a storey can be built at.
E_IMPORT_BAD_SPEC error Malformed import spec.
E_IMPORT_CONFLICT error Imported name conflicts with an existing component.
E_IMPORT_CYCLE error Cyclic import.
E_IMPORT_NOT_EXPORTED error Imported name is not exported by the module.
E_IMPORT_NOT_FOUND error Import path could not be resolved.
E_IMPORT_PARSE error Imported module has a parse error.
E_INDEX error Array index out of range.
E_INTENT_NO_DOOR error The plan has no modeled entrance, so reachable cannot hold.
E_INTENT_NO_SITE error An intent asserts a SYMBOLIC window facing against a plan with no site.
E_INTENT_NO_WINDOW error A room the brief wants a window in has too few.
E_INTENT_NOT_ADJACENT error Two rooms the brief wants adjacent share no interior door.
E_INTENT_ROOM_AREA error A named room's floor area is outside the brief's band.
E_INTENT_ROOM_COUNT error The plan's room count does not match the brief.
E_INTENT_ROOM_MISSING error A room the brief names is absent from the plan.
E_INTENT_TOTAL_AREA error The plan's total floor area is outside the brief's band.
E_INTENT_UNREACHABLE error A room cannot be reached from the entrance through modeled doors.
E_JSON_KIND error Unknown element kind in plan JSON.
E_JSON_SCHEMA error Plan JSON does not match the schema.
E_LAYOUT_CYCLE error Relational room placement forms a cycle.
E_LAYOUT_REF error Relational placement references an unknown room.
E_LEVEL_DUP error Two level blocks declare the same storey number.
E_LEVEL_MIX error A drawable statement sits beside level blocks.
E_LEVEL_NEST error level used inside a block or component.
E_OPENING_ABOVE_WALL error An opening's head is above the wall it is cut in.
E_OPENING_WIDTH error Opening must have a positive width.
E_OUTDOOR_POLY_DEGENERATE error An outdoor ring is degenerate, or a balcony was given one.
E_OUTDOOR_POLY_SELF_INTERSECT error An outdoor ring crosses itself.
E_OUTDOOR_RAIL error A rail clause on something that is not a balcony, or an unknown edge word.
E_OUTDOOR_SIZE error An outdoor surface must have a positive size.
E_PARSE error The source could not be read: its SHAPE is wrong.
E_PLACE_POLY error A rectangle-only placement clause aimed at a polygon room.
E_PLACE_REF error Furniture placed in an unknown or non-absolute room.
E_PNG_DEPENDENCY error PNG/PDF export needs an optional dependency that is not installed.
E_RANGE_LIMIT error Range too large.
E_RECURSION error Component recursion too deep.
E_REDEF error Name already defined in this scope.
E_ROOF_AMBIGUOUS error roof overhang cannot tell which wall ring to follow.
E_ROOF_CURVED error roof overhang on a wall with a curved edge.
E_ROOF_OVERHANG error roof overhang is zero or negative.
E_ROOF_PLACEMENT error roof used inside a component body.
E_ROOF_POLY_DEGENERATE error roof polygon outline has fewer than 3 effective vertices.
E_ROOF_SELF_INTERSECT error The roof outline crosses itself.
E_ROOF_WALL error roof overhang … wall <id> names a wall that cannot carry a roof.
E_ROOM_ALIGN error Unknown relational alignment edge.
E_ROOM_ALIGN_AXIS error Relational alignment edge belongs to the other axis.
E_ROOM_POLY_DEGENERATE error Polygon room has fewer than three effective vertices.
E_ROOM_POLY_SELF_INTERSECT error Polygon room intersects itself.
E_ROOM_RADIUS error Circular room needs a positive radius.
E_ROOM_SIZE error Room must have a positive size.
E_SILL_ABOVE_HEAD error A window's sill sits at or above its head.
E_SITE_BOUNDARY_DEGENERATE error The site boundary encloses no lot.
E_SITE_BOUNDARY_SELF_INTERSECT error The site boundary crosses itself.
E_SITE_DUP error Two site blocks in one plan.
E_SITE_NO_STREET error A site block declares no street.
E_STAIR_WIDTH error Stair flight width is outside the footprint.
E_STRIP_NEST error Illegal strip nesting.
E_STRIP_SIZE error Room in a strip is missing a size.
E_TYPE error Type mismatch.
E_UNKNOWN_COMPONENT error Unknown component.
E_UNKNOWN_FN error Unknown function.
E_UNKNOWN_REF error Unknown reference.
E_VERT_SIZE error Vertical circulation must have a positive size.
E_VOID_SIZE error A floor void must have a positive size.
E_WALL_THICKNESS error Wall must have a positive thickness.
E_WHILE_LIMIT error while exceeded its iteration cap.
E_WINDOW_WIDTH error Window must have a positive width.
W_ALIAS_MATCH warning A room's use was inferred from an indirect alias, not stated.
W_BALCONY_NO_DOOR warning A balcony with no way onto it.
W_BATH_VIA_BEDROOM warning Bathroom is reachable only through a bedroom.
W_BEDROOM_NO_WINDOW warning Bedroom has no window.
W_CIRCUITOUS_PATH warning A room is reached by a very roundabout path.
W_DIM_INSIDE warning A hand-written dimension line lands inside the building.
W_DIM_NO_WALL warning A dim faces/dim clear endpoint has no wall to measure to.
W_DIM_OVERLAP warning Two hand-written dimensions are drawn on top of each other.
W_DOOR_CLEARANCE warning Door is narrower than the minimum clear width.
W_DOOR_NEAR_CORNER warning A door leaves less wall between its jamb and a corner than the wall is thick.
W_DOOR_OFF_WALL warning Door does not lie on any wall.
W_DOORWAY_BLOCKED warning A doorway's landing is blocked.
W_DRAWING_OVERFLOW warning The whole drawing does not fit the declared paper, even though the building does.
W_DUP_ACC_METADATA warning Duplicate accTitle/accDescr.
W_EMPTY_PLAN warning Empty plan.
W_FIXTURE_BACK_TO_ROOM warning A fixture stands against a wall but faces the wrong way.
W_FIXTURE_FLOATING warning A plumbing/kitchen fixture is not against a wall.
W_FIXTURE_WRONG_ROOM warning Fixture is not inside its declared room.
W_FURN_CLEARANCE warning A fixture's use-space is blocked.
W_FURNITURE_OVERLAP warning Two pieces of furniture overlap.
W_FURNITURE_WALL_COLLISION warning Furniture penetrates a wall.
W_GARAGE_TOO_NARROW warning A garage is too narrow to park in.
W_HATCH_SCALE warning Hatch scale must be positive; using 1.
W_IMPORT_EMPTY_FILE warning Whole-file import binds an empty component.
W_NO_ENTRANCE warning The plan has no exterior door.
W_OPENING_OFF_WALL warning Opening does not lie on any wall.
W_OUTDOOR_OVERLAPS_ROOM warning A ground surface is laid over a room's floor.
W_PATH_TOO_NARROW warning The walk to a room squeezes below a passable width.
W_POCKET_RUN warning A pocket door has no wall to slide into.
W_ROOM_DISCONNECTED warning Room has no door — it can't be entered.
W_ROOM_LABEL_OUTSIDE warning A room's explicit label anchor falls outside the room.
W_ROOM_NO_CLEAR_PATH warning A room cannot be entered or crossed.
W_ROOM_NO_FIXTURE warning Bathroom or kitchen has no fixtures.
W_ROOM_NOT_ENCLOSED warning Bathroom is not fully enclosed.
W_ROOM_NOT_EQUATOR_FACING warning A habitable room has windows, but none faces the equator side.
W_ROOM_OVERLAP warning Rooms overlap.
W_ROOM_TOO_SMALL warning Room is implausibly small.
W_ROOM_UNREACHABLE warning Room cannot be reached from the entrance.
W_SANITIZED_CONFIG warning A disallowed config value was stripped.
W_SCALE_OVERFLOW warning The drawing does not fit the declared paper at the declared scale.
W_STAIR_UNMATCHED warning A run of vertical circulation appears on only one storey.
W_SWING_OBSTRUCTED warning Door swing is obstructed.
W_SWING_ROOM_NOT_ADJACENT warning swing into <room> names a room the door does not border.
W_UNKNOWN_MATERIAL warning Unknown wall material; using the default hatch.
W_UNKNOWN_STYLE_KEY warning Unknown style key.
W_UNKNOWN_THEME_KEY warning Unknown theme key.
W_WINDOW_OFF_WALL warning Window does not lie on any wall.

E_ACC_PLACEMENT

erroraccTitle/accDescr used outside the plan level.

Cause. An accTitle or accDescr accessibility-metadata statement appeared inside a component or a control-flow block. They describe the whole plan, so they are only legal as direct plan-level statements.

Fix. Move the accTitle/accDescr line up to the plan body, alongside units/north.

component c() { accDescr "x" }   # error: only allowed at plan level

E_ARC_RADIUS

error — Arc radius too small for its chord.

Cause. An arc (x,y) radius R edge asks for a circle of radius R through the previous vertex and this one, but R is less than half the straight-line distance between them (or is not positive) — no such circle exists.

Fix. Raise the radius to at least half the chord (the message states the minimum), or move the endpoints closer together. arch fix applies the minimum for you.

wall exterior thickness 200 { (0,0) arc (10000,0) radius 3000 }   # error: needs R >= 5000

E_ARGCOUNT

error — Component called with the wrong number of arguments.

Cause. A component instance supplies more or fewer arguments than the component declares parameters.

Fix. Pass exactly one argument per declared parameter.

component bed(x, y) { … }
bed(300)        # error: expects 2 arguments

E_ARITY

error — Built-in function called with the wrong number of arguments.

Cause. A built-in (e.g. abs, sqrt, len) was called with the wrong argument count.

Fix. Check the function's arity; most built-ins take one argument.

let x = abs(1, 2)   # error: abs expects 1 argument

E_ASSIGN_UNDEF

error — Assignment to an undeclared name.

Cause. NAME = value was used for a name never introduced with let.

Fix. Declare it first with let, or fix a typo in the name.

x = 5           # error: declare with `let x = …` first

E_ATTACH_POS_RANGE

error — Opening attachment position is out of range.

Cause. The at <pos> of an attached opening is outside the host wall: a percentage outside 0–100%, a millimetre distance outside 0 … wall length, or — since the position may be an expression — a value that is not a finite number at all.

Fix. Use a percentage in 0–100%, a millimetre distance within the wall's run, or center. The non-finite case carries no fix: there is no nearest legal value to clamp to, so check the expression that produced it.

door on w1 at 150% width 900   # error: 150% is past the wall end

E_ATTACH_WALL_REF

error — Opening attached to an unknown or ambiguous wall.

Cause. A door/window/opening … on <wall> at <pos> names a wall id (or category) that no wall has, or one that matches more than one wall — so the compiler cannot pick the polyline to walk.

Fix. Reference an existing, unique wall id (add id= to the wall if needed).

door on w1 at 40% width 900   # error if no wall id=w1 (or several match)

E_CALL_DEPTH

error — Value-function call stack too deep.

Cause. A value-function recurses (directly or mutually) beyond the call-depth limit.

Fix. Make the recursion terminate, or rewrite it iteratively with a bounded while.

let f(n) = f(n + 1)   # error: never terminates

E_COLUMN_SIZE

error — Column must have a positive size.

Cause. A column's width or height evaluated to zero or a negative number.

Fix. Give the column a positive size W x H.

column at (0,0) size 0x300   # error: width is 0

E_DIM_CURVE_REF

error — Invalid dim radius/dim diameter reference.

Cause. A curve call-out references an element that does not exist, is not the right shape (a diameter on a rectangular room, a radius on a wall with no arc edge), matches several walls, or omits segment <n> on a wall with more than one arc. The compiler will not guess which curve was meant.

Fix. Name an existing, unique wall id whose edge is an arc (adding segment <n> when it has several), or an existing room circle id for diameter.

dim radius w1   # error if w1 is straight, unknown, or has two arc edges

E_DIV_ZERO

error — Division or modulo by zero.

Cause. An expression divides (or takes a remainder) by a value that evaluates to zero.

Fix. Guard the divisor, or use a non-zero value.

let x = 10 / 0   # error

E_DOMAIN

error — Math domain error.

Cause. A built-in received an out-of-domain argument (e.g. sqrt of a negative number).

Fix. Pass a value within the function's domain.

let x = sqrt(-1)   # error

E_DOOR_KIND_CLAUSE

error — That clause is not available on this kind of door.

Cause. A door statement carries a clause its kind has no meaning for: hinge on any of the sliding family (sliding/barn/bifold/pocket — nothing is hinged to a jamb), swing on a sliding or pocket door (the panel stays in the plane of the wall, or inside it), or slide/open on a hinged door (nothing travels along the wall). ArchLang refuses rather than draws the statement as if the clause were absent — silently ignoring a written clause is the silent-error design this project rules out (the v1.23 precedent: rectangle-only clauses REFUSE a polygon room rather than approximate it).

Fix. Delete the clause (the machine-applicable fix does exactly that), or change the door's kind to one the clause belongs to. swing on a barn or bifold door is legal and means which FACE of the wall the panel hangs on or folds toward — it is not a leaf arc.

door pocket on w1 at 50% width 900 hinge left   # error: a pocket door has no hinge

E_DOOR_KIND_CURVED

error — A non-hinged door kind cannot sit on a curved wall.

Cause. The panel of a sliding, barn, bifold or pocket door is a straight rectangle running along a straight track, and its pocket/track geometry is straight by construction — none of that survives on a wall whose hosting edge is an arc. A hinged leaf does survive (its swing is taken from the tangent at the doorway), so only the sliding family is refused. Refusing is deliberate: drawing a straight panel across a curved reveal would be a wrong drawing with no diagnostic.

Fix. Use a hinged door on the curve (the default — delete the kind word), or move the door onto one of the wall's straight runs.

wall w1 thickness 200 { (0,0) arc (6000,0) radius 4000 }
door pocket on w1 at 50% width 900   # error: curved host

E_DOOR_OPEN_RANGE

erroropen must be between 0 and 1.

Cause. open <f> is the fraction of its travel a sliding-family panel is DRAWN at — 0 is closed, 1 fully open — so a value outside [0,1] names a position the panel cannot reach. It is a drawing fact only: nothing measured (lint, describe, the intent channel) reads it, so a half-open door can never silence a clearance warning.

Fix. Give open a fraction in [0,1]; arch fix clamps it to the nearer end for you. Omit it entirely for the default 0.5.

door sliding on w1 at 50% width 1200 open 1.5   # error: outside [0,1]

E_DOOR_WIDTH

error — Door must have a positive width.

Cause. A door's width evaluated to zero or a negative number.

Fix. Give the door a positive width.

door at (0,0) width 0   # error

E_DOTTED_DECL

error — A dotted name cannot be declared.

Cause. A dotted name like west.main addresses an element INSIDE a placed instance. The namespace belongs to the place, so a dotted name is only ever a reference — it can never be declared with id=, let, as, or for.

Fix. Declare the short name and address it from outside as <instance>.<name>.

room id=main at (0,0) size 3000x3000   # then, in the plan: furniture bed in west.main centered

E_DUP_ID

error — Duplicate element id.

Cause. Two elements declare the same id=…; ids must be unique across the plan.

Fix. Rename one of them, or drop the explicit id to auto-generate a unique one.

room id=a at (0,0) size 1x1
room id=a at (1,0) size 1x1   # error: duplicate id "a"

E_DUP_INSTANCE

error — Duplicate place … as <name> instance name.

Cause. Two place statements claim the same instance name. The name is the id NAMESPACE for everything inside the instance, so reusing it would silently merge two instances' ids.

Fix. Give each instance its own name (as west / as east).

place wing() as west at (0,0)
place wing() as west at (9000,0)   # error: instance "west" already used

E_FENCE_CURVED

error — A fence cannot have a curved (arc) edge.

Cause. An arc … radius … clause appeared inside a fence { … } body. The post pitch, the panel offset and the reported length_mm are all measured along a STRAIGHT run, so a faceted curve would silently measure the facets rather than the arc — this release refuses rather than approximating (the same decision roof makes with E_ROOF_CURVED).

Fix. Approximate the curve with short straight runs, which is what a fence built on a curve actually is.

fence picket { (0,0) arc (3000,3000) radius 3000 }   # error: curved edge

E_FURN_AGAINST

error — Invalid against wall fixture placement.

Cause. A wall-anchored fixture references an unknown wall, omits segment on a multi-segment wall, omits side, sits on a non-axis-aligned segment, has an out-of-range offset, or also sets rotate. The compiler will not guess which wall/side/segment was meant.

Fix. Name an existing wall id, add segment <n> for multi-segment walls, give side left|right, keep the segment axis-aligned, and drop any explicit rotate.

furniture wc against wall w1 side left size 400x700   # error if w1 is unknown or multi-segment

E_FURN_FLUSH

errorflush on a placement that touches no edge.

Cause. flush measures inset from the inner face of the wall behind an anchored edge. A centered piece (or the equivalent anchor center) is pushed against no edge, so there is no wall face to measure from.

Fix. Anchor the piece to the edge you want it flush with (anchor bottom flush, anchor top-left flush), or drop flush and keep it centred.

furniture wc in bath centered flush size 400x700   # error: centred, so nothing to be flush with

E_FURN_ROOM

error — Furniture placed in an unknown room.

Cause. A furniture item names a room with in <roomId>, but no room has that id.

Fix. Use the id of an existing room id=…, or drop the in clause.

furniture bed at (0,0) size 1500x2000 in bedrm   # error: no room id=bedrm

E_FURN_ROTATE

error — Furniture rotation must be a quarter-turn.

Cause. A furniture item's rotate is not one of 0, 90, 180, or 270 degrees.

Fix. Use a quarter-turn: rotate 0|90|180|270.

furniture wc at (0,0) size 400x700 rotate 45   # error: not a quarter-turn

E_FURN_SIZE

error — Furniture must have a positive size.

Cause. A furniture item's width or height evaluated to zero or a negative number.

Fix. Give the item a positive size W x H.

furniture bed at (0,0) size 0x2000   # error

E_HEIGHT_RANGE

error — A height is outside the range a storey can be built at.

Cause. A height, sill or head clause evaluated to a number no building has: zero or negative, not finite, or above 100 m. A wall or a head at zero is not a low one, it is a missing one. A window sill of exactly 0 is the one exception and is legal — it means a floor-length window. The range guards the ENDS, not the units: heights are millimetres like every other number in the language, so height 3 is three millimetres, is inside the range, and is accepted — the compiler will not guess that three metres was meant, because that would put a number in the datum the author never wrote.

Fix. Write the height in millimetres, or drop the clause and inherit the default (the fix does exactly that) — 3000 for a storey, 2100 for a door or window head, 900 for a window sill.

wall id=w1 exterior thickness 200 height 0 { (0,0) (4000,0) close }   # error: a wall with no height

E_IMPORT_BAD_SPEC

error — Malformed import spec.

Cause. The string after import is not a recognizable module reference.

Fix. Use a relative path ("lib/x.arch") or a namespaced spec ("@scope/name:1.0.0").

import "???" : a   # error

E_IMPORT_CONFLICT

error — Imported name conflicts with an existing component.

Cause. An imported component has the same name as one already defined or imported.

Fix. Rename with as, or remove the duplicate.

import "lib.arch": bed as lib_bed

E_IMPORT_CYCLE

error — Cyclic import.

Cause. Modules import each other in a cycle, which cannot be resolved.

Fix. Break the cycle so module dependencies form a tree.

# a.arch imports b.arch which imports a.arch  → error

E_IMPORT_NOT_EXPORTED

error — Imported name is not exported by the module.

Cause. The module has no component with the requested name.

Fix. Import a name the module actually defines (check its components).

import "lib.arch": nope   # error if lib.arch has no `component nope`

E_IMPORT_NOT_FOUND

error — Import path could not be resolved.

Cause. The World could not read the module at the given path.

Fix. Check the path (relative to the importing file) and that the file exists.

import "lib/missing.arch": a   # error

E_IMPORT_PARSE

error — Imported module has a parse error.

Cause. The module referenced by import does not itself parse.

Fix. Fix the syntax error in the imported module.

# error originates in the imported file

E_INDEX

error — Array index out of range.

Cause. arr[i] used an index outside 0 .. len(arr) - 1.

Fix. Clamp or check the index against len(arr).

let a = [1, 2]
let x = a[5]   # error

E_INTENT_NO_DOOR

error — The plan has no modeled entrance, so reachable cannot hold.

Cause. An intent asserts reachable: true, but the plan has no door connecting a room to the exterior — nothing is enterable, so no room is reachable.

Fix. Add an exterior entrance door on a perimeter wall. Advisory tier: reported and scored by validateIntent but does NOT fail ok (gate: false).

door on exterior at 50% width 900   # a front door

E_INTENT_NO_SITE

error — An intent asserts a SYMBOLIC window facing against a plan with no site.

Cause. An intent roomsInclude[].windows.facing names one of the derived directions (street, back, equator_side, sunrise_side, sunset_side) but the plan declares no site block, so there is nothing to resolve the name against. The question is unanswerable, not answered no.

Fix. Declare site { street … } in the plan (that is what gives the derived names their letters), or assert a plain compass letter instead. Gating tier: this failure fails validateIntent's ok — it is a refusal, never a silent pass and never a silent miss.

plan "H" {
  units mm
  site { street south }   # now `facing: "equator_side"` resolves to "S"
}

E_INTENT_NO_WINDOW

error — A room the brief wants a window in has too few.

Cause. An intent roomsInclude[].windows requires at least one window in a concept's room(s) (e.g. "give the bedroom a window"), but the plan places fewer than the required count.

Fix. Add a window on one of that room's walls. Gating tier: this failure DOES fail validateIntent's ok.

window on north at 40% width 1200   # light the bedroom

E_INTENT_NOT_ADJACENT

error — Two rooms the brief wants adjacent share no interior door.

Cause. An intent adjacency edge names two concepts (e.g. hall ↔ bathroom) that are not joined by an interior door or cased opening in the plan's modeled connectivity.

Fix. Add a door (or opening) on the wall the two rooms share so they are directly connected. Advisory tier: this is scored and reported by validateIntent but does NOT fail ok (gate: false) — one-shot topology is what the loop tools address.

door on wall_hall_bath width 800   # connect the hall to the bathroom

E_INTENT_ROOM_AREA

error — A named room's floor area is outside the brief's band.

Cause. An intent roomsInclude[].areaM2 gives a per-room area band (from a number in the brief, ±10% for "about N"), but the matched room's area falls outside it.

Fix. Resize the room so its floor area lands in the band. Gating tier: this failure fails validateIntent's ok. Assert a band only where the brief states a number — qualitative size words license none.

room at (0,0) size 4000x3000 label "Bedroom"   # 12 m²

E_INTENT_ROOM_COUNT

error — The plan's room count does not match the brief.

Cause. An intent rooms count (asserted only when the brief ENUMERATES its rooms) does not match the plan's room total. A single surplus room passes only when it is pure circulation (a hall/corridor) — policy B.

Fix. Add or remove rooms to reach the enumerated count. Gating tier: this failure fails validateIntent's ok.

# brief lists 4 rooms; the plan draws 5 (and the extra is a bedroom, not a hall)

E_INTENT_ROOM_MISSING

error — A room the brief names is absent from the plan.

Cause. An intent roomsInclude[] concept (e.g. "bathroom") matched no room by label, room_type, or uses — the plan is missing a room the brief asked for.

Fix. Add a room whose label, uses, or type matches the concept. Gating tier: this failure fails validateIntent's ok.

room at (0,0) size 2000x2000 label "Bathroom" uses bath   # supply the missing room

E_INTENT_TOTAL_AREA

error — The plan's total floor area is outside the brief's band.

Cause. An intent totalAreaM2 band (from a number in the brief, ±10% for "about N") does not contain the plan's total floor area.

Fix. Grow or shrink rooms so the total lands in the band. Gating tier: this failure fails validateIntent's ok. Assert a band only where the brief states a number.

# brief says "about 42 m²" (band 37.8–46.2); the plan totals 52 m²

E_INTENT_UNREACHABLE

error — A room cannot be reached from the entrance through modeled doors.

Cause. An intent asserts reachable: true and the plan HAS an entrance, but one or more rooms are cut off — no chain of modeled doors reaches them from the exterior.

Fix. Add interior doors so every room connects back to the entrance. Advisory tier: reported and scored by validateIntent but does NOT fail ok (gate: false).

door on wall_hall_store width 800   # connect the isolated room

E_JSON_KIND

error — Unknown element kind in plan JSON.

Cause. An element in the JSON names a kind (or lives in an array) the builder does not recognize — e.g. an opening whose kind is not door, window, or opening.

Fix. Use one of the supported kinds: opening kind must be door | window | opening.

{ "openings": [ { "kind": "portal", "width": 900 } ] }   # error at /openings/0/kind: unknown kind "portal"

E_JSON_SCHEMA

error — Plan JSON does not match the schema.

Cause. A value passed to planFromJson has the wrong shape or type for its JSON path (e.g. a room missing a numeric width, a non-array rooms), or it uses a construct the JSON form cannot represent — scripting (let/for/if/component) and import are intentionally not supported.

Fix. Fix the value at the reported JSON path (the message names it, e.g. /rooms/0/width); express geometry as concrete numbers, and author scripting/imports in .arch source instead.

{ "rooms": [ { "x": 0, "y": 0, "width": "big", "height": 3000 } ] }   # error at /rooms/0/width: expected a number

E_LAYOUT_CYCLE

error — Relational room placement forms a cycle.

Cause. Rooms placed with right-of/below/… reference each other in a loop, so no order resolves them.

Fix. Break the cycle by giving one of the rooms absolute at (x,y) coordinates.

room id=a right-of b size 100x100
room id=b left-of a size 100x100   # error: a ↔ b cycle

E_LAYOUT_REF

error — Relational placement references an unknown room.

Cause. A right-of/below/… clause names a room id that does not exist in the plan.

Fix. Reference an existing room id, or fix the typo.

room id=k right-of ghost size 100x100   # error: no room "ghost"

E_LEVEL_DUP

error — Two level blocks declare the same storey number.

Cause. Level numbers identify the storeys of one building, so each may be declared once; two level 1 blocks would produce two pages both claiming to be level 1.

Fix. Renumber one of them, or merge the two bodies into a single level block.

level 1 { room at (0,0) size 3000x3000 }
level 1 { room at (0,0) size 3000x3000 }   # error: level 1 twice

E_LEVEL_MIX

error — A drawable statement sits beside level blocks.

Cause. A plan is either single-storey (no level block) or entirely made of them: anything that draws belongs to exactly one storey, so a room/wall/door/for/strip/component call at plan level next to a level block has no storey to belong to.

Fix. Move the statement inside the level block it belongs to. Only settings (units/grid/paper/scale/north/site/dims/title/axes/schedule/legend), component/import declarations, and the plan-global let/set stay outside — they apply to every level.

plan "H" {
  room at (0,0) size 3000x3000   # error: move it into a level
  level 1 { wall exterior thickness 200 { (0,0) (3000,0) close } }
}

E_LEVEL_NEST

errorlevel used inside a block or component.

Cause. A level block is a plan-level statement: it partitions the whole plan into storeys, so it cannot be nested inside another level, a for/if/while body, a strip, or a component definition.

Fix. Move the level block out to the plan body. To draw the same content on several storeys, put it in a component and call it from each level.

component c() { level 1 { } }   # error: only allowed at plan level

E_OPENING_ABOVE_WALL

error — An opening's head is above the wall it is cut in.

Cause. A door/window/opening whose head exceeds its host wall's own height would run out through the top of the wall. The wall's height is the authored wall … height, else this storey's, else the 3000 mm default — so this fires on a low parapet or a short storey as readily as on a mistyped head.

Fix. Lower the head to the wall's height (the fix does exactly that), or raise the wall with wall … height.

wall id=w1 exterior thickness 200 height 2200 { (0,0) (4000,0) close }
  door id=d on w1 at 50% width 900 head 2400   # error: head above a 2200 wall

E_OPENING_WIDTH

error — Opening must have a positive width.

Cause. A cased opening's width evaluated to zero or a negative number.

Fix. Give the opening a positive width.

opening at (0,0) width 0   # error

E_OUTDOOR_POLY_DEGENERATE

error — An outdoor ring is degenerate, or a balcony was given one.

Cause. Either an outdoor … polygon … ring has fewer than 3 effective vertices once duplicate and collinear points are removed (so it encloses no area), or the ring was written on a balcony, which is rectangle-only: a balcony's railing is derived per EDGE — top, bottom, left, right — and a ring has no such edges.

Fix. Give the ring at least 3 corners that are not all on one line. For a balcony, use at (x,y) size WxH; a polygonal balcony is deferred by name, not supported.

outdoor paving polygon (0,0) (1000,0) (2000,0)   # error: all three are collinear

E_OUTDOOR_POLY_SELF_INTERSECT

error — An outdoor ring crosses itself.

Cause. The vertices of an outdoor … polygon … describe a ring whose edges intersect (a bow-tie), so it encloses no single area — there is no unambiguous surface to hatch or to measure. Usually two vertices in the wrong order.

Fix. Reorder the vertices so the ring is a simple polygon, walking the outline once without crossing back over itself.

outdoor deck polygon (0,0) (4000,4000) (4000,0) (0,4000)   # error: a bow-tie

E_OUTDOOR_RAIL

error — A rail clause on something that is not a balcony, or an unknown edge word.

Cause. rail names which edges carry a railing, and only a balcony has one. Written on any other ground surface it has no meaning — and a clause with no meaning is refused rather than silently dropped, so a plan never draws differently from what it says. The same code covers an edge word outside top|bottom|left|right|all|none.

Fix. Delete the clause, or make the surface an outdoor balcony. For an unknown word, use one of the six edge words.

outdoor deck at (0,0) size 3000x2000 rail all   # error: a deck has no railing

E_OUTDOOR_SIZE

error — An outdoor surface must have a positive size.

Cause. An outdoor … at (x,y) size WxH statement's width or height evaluated to zero or a negative number, so there is no ground to draw, hatch or measure.

Fix. Give it a positive size W x H — the surface's extent in plan. For a shape that is not a rectangle, use the polygon spelling instead.

outdoor lawn at (0,0) size 0x4000   # error: zero width

E_PARSE

error — The source could not be read: its SHAPE is wrong.

Cause. The lexer or the parser could not make a statement out of the bytes at this span — a missing or misspelled keyword, a value where a keyword belongs, an unterminated string, an unbalanced brace, clauses written in the wrong order. It is the one code that says nothing about what the plan MEANS: resolution never ran here, so no measurement, no geometry and no soundness rule had a chance to speak.

Fix. Read the message: it names what was expected and what was found, at a byte span. Compare the statement against arch spec's one line for that keyword — clause ORDER is part of the grammar, not a suggestion. Unlike every other code in this catalog, there is no machine-applicable fix to apply, because the compiler has no reading of the text to correct.

door on w1 at 40% width 900 wall w1   # error: `wall` pairs with the `at (x,y)` form only

E_PLACE_POLY

error — A rectangle-only placement clause aimed at a polygon room.

Cause. Relational room placement (right-of/left-of/below/above) and room-relative furniture placement (in <room> centered|anchor …) are closed-form arithmetic on a room's four RECTANGLE edges. A room polygon has no such edges, and its bounding box is not its floor — an anchor could land the piece in a notch that is outside the room — so the compiler refuses instead of guessing (ADR 0005).

Fix. Place the room or the fixture with explicit at (x,y) coordinates (a fixture may add rotate), or make the referenced room rectangular.

room id=L polygon (0,0) (6000,0) (6000,4000) (3000,4000) (3000,6000) (0,6000)
furniture wc in L anchor bottom-left   # error: L is a polygon room

E_PLACE_REF

error — Furniture placed in an unknown or non-absolute room.

Cause. A furniture … in <room> centered|anchor … names a room that does not exist, or one positioned relationally (right-of/…) whose box is not yet fixed when the fixture is placed.

Fix. Reference an existing room given absolute at (x,y) coordinates.

furniture bed in bedrm centered size 1500x2000   # error: no room id=bedrm

E_PNG_DEPENDENCY

error — PNG/PDF export needs an optional dependency that is not installed.

Cause. Rendering to PNG needs @resvg/resvg-js (PDF needs pdfkit); the optional binary is absent in this environment (it is not bundled, to keep the core zero-dependency).

Fix. Install the optional dependency (npm install @resvg/resvg-js), or re-run with --install to fetch it automatically, or render to SVG/DXF (zero-dependency).

arch preview plan.arch --install   # fetches @resvg/resvg-js, then renders the PNG

E_RANGE_LIMIT

error — Range too large.

Cause. A lo..hi range would expand to more elements than the safety cap allows.

Fix. Use a smaller range, or restructure to avoid materializing it.

for i in 0..1000000 { … }   # error: range too large

E_RECURSION

error — Component recursion too deep.

Cause. Component instantiation nested beyond the depth limit (usually unbounded self-instantiation).

Fix. Add a base case so the recursion terminates.

component r(n) { r(n) }   # error: never terminates

E_REDEF

error — Name already defined in this scope.

Cause. A let re-declares a name already bound in the same scope.

Fix. Rename one binding, or use NAME = … to reassign instead of redeclaring.

let x = 1
let x = 2   # error: redefinition

E_ROOF_AMBIGUOUS

errorroof overhang cannot tell which wall ring to follow.

Cause. The overhang sugar offsets ONE closed wall ring, and with no wall <id> clause it infers that ring as the plan's single closed exterior wall. The plan has none, or has more than one, so there is nothing to infer — and picking the first would silently draw a roof over part of the building.

Fix. Name the ring (roof overhang 600 wall <id>), or state the outline yourself with roof polygon (x,y) (x,y) (x,y) ….

plan "H" {
  units mm
  room id=r1 at (0,0) size 4000x3000
  roof overhang 600   # error: no closed exterior wall to follow
}

E_ROOF_CURVED

errorroof overhang on a wall with a curved edge.

Cause. The named ring has an arc edge. Offsetting a curve is a different construction from mitring two straight faces (concentric radii, plus the cases where the offset radius passes through zero), and faceting it would put a tessellation in the one place a reader is entitled to read a true parallel.

Fix. State the outline explicitly with roof polygon …, or follow a straight-edged wall ring instead.

wall id=drum exterior thickness 200 { (0,0) arc (6000,0) radius 4000 (6000,4000) (0,4000) close }
roof overhang 600 wall drum   # error: arc edge

E_ROOF_OVERHANG

errorroof overhang is zero or negative.

Cause. An overhang is a distance the roof projects PAST the wall's outer face, so it must be positive. Zero would draw the outline on the wall face (say nothing instead), and a negative value would draw it inside the building.

Fix. Give a positive projection in mm, e.g. roof overhang 600.

roof overhang 0   # error: must be positive

E_ROOF_PLACEMENT

errorroof used inside a component body.

Cause. A roof belongs to a building, not to a reusable part of one: roof overhang is offset from the plan's closed exterior wall ring, and a component is authored in its own local frame with no such ring. Two placed copies would each derive an outline and the plan would draw two roofs.

Fix. Move the roof line out to the plan body (or into the level block it belongs to).

component wing() { roof overhang 600 }   # error: only allowed at plan level

E_ROOF_POLY_DEGENERATE

errorroof polygon outline has fewer than 3 effective vertices.

Cause. After removing duplicate and straight-through (collinear) points the ring encloses no area, so it is a line or a point rather than a roof outline.

Fix. Give at least three vertices that actually turn a corner.

roof polygon (0,0) (4000,0) (8000,0)   # error: all three are collinear

E_ROOF_SELF_INTERSECT

error — The roof outline crosses itself.

Cause. Either the roof polygon ring was written as a bow-tie, or the derived overhang offset is wide enough to swallow a notch in the wall it follows (a 900 mm eave across a 600 mm light well) and the pushed-out faces cross. Neither encloses a single area.

Fix. Reorder the vertices, or reduce the overhang — or state the outline explicitly with roof polygon ….

roof polygon (0,0) (4000,4000) (4000,0) (0,4000)   # error: bow-tie

E_ROOF_WALL

errorroof overhang … wall <id> names a wall that cannot carry a roof.

Cause. The named wall is not declared in this plan, or it is not a closed ring. An overhang is offset from a loop; an open polyline has no inside to be outside of.

Fix. Check the id, and give the wall a close so its points form a ring.

wall id=w1 exterior thickness 200 { (0,0) (8000,0) }
roof overhang 600 wall w1   # error: not a closed ring

E_ROOM_ALIGN

error — Unknown relational alignment edge.

Cause. A relationally-placed room's align <word> names something that is not an alignment edge. The set is closed (top, middle, bottom for right-of/left-of; left, center, right for below/above), and an unrecognised word used to fall through to the leading edge silently — drawing the plan as if align had never been written.

Fix. Use one of the six edges; the diagnostic suggests the nearest one and carries a fix that rewrites just that word.

room id=b right-of a align sideways size 3000x3000   # error: not an edge (did you mean `bottom`?)

E_ROOM_ALIGN_AXIS

error — Relational alignment edge belongs to the other axis.

Cause. A relationally-placed room's align <edge> names a real edge, but not one of the axis that direction aligns on. A horizontal relation (right-of/left-of) offsets its room vertically, so it takes top|middle|bottom; a vertical relation (below/above) offsets horizontally, so it takes left|center|right. (middle and center are honoured on both — they are the same instruction spelled twice.) A cross-axis edge used to be ignored in silence, drawing the room against the leading edge exactly as if align had never been written — distinct from E_ROOM_ALIGN, where the word is not an edge at all.

Fix. Use the edge of the correct axis; the diagnostic names its exact counterpart (leading stays leading, trailing stays trailing) and carries a fix that rewrites just that word.

room id=b right-of a align right size 3000x3000   # error: `right` is horizontal (did you mean `bottom`?)

E_ROOM_POLY_DEGENERATE

error — Polygon room has fewer than three effective vertices.

Cause. After removing duplicate and straight-through (collinear) points, the ring encloses no area — so it has no floor, no centroid and no containment test.

Fix. Give the room at least three vertices that actually turn a corner.

room polygon (0,0) (4000,0) (8000,0)   # error: all three are collinear

E_ROOM_POLY_SELF_INTERSECT

error — Polygon room intersects itself.

Cause. Two of the ring's edges cross (or run along each other), so the polygon is not simple and which side is 'inside' is undefined — area, containment and adjacency would all be meaningless.

Fix. Reorder the vertices so the ring is traced once around the room without crossing itself (a bow-tie usually means two vertices are swapped).

room polygon (0,0) (4000,4000) (4000,0) (0,4000)   # error: bow-tie

E_ROOM_RADIUS

error — Circular room needs a positive radius.

Cause. A room circle at (cx,cy) radius R has R of zero or less, so it encloses no floor — there is no area, no centroid and no containment test to compute.

Fix. Give the room a positive radius in millimetres.

room circle at (5000,5000) radius 0   # error: no floor

E_ROOM_SIZE

error — Room must have a positive size.

Cause. A room's width or height evaluated to zero or a negative number.

Fix. Give the room a positive size W x H.

room at (0,0) size 0x4000   # error: width is 0

E_SILL_ABOVE_HEAD

error — A window's sill sits at or above its head.

Cause. A window's sill is the bottom of the glazing and its head is the top, both measured from this storey's floor. When the sill is not below the head there is no opening between them — the statement describes a window with no glass in it. Refused rather than silently swapped: which of the two numbers is wrong is not something the compiler can know.

Fix. Lower the sill below the head, or raise the head. Dropping the sill clause (the fix) restores the 900 mm default.

window id=w on wall1 at 50% width 1200 sill 2400 head 2100   # error: sill above head

E_SITE_BOUNDARY_DEGENERATE

error — The site boundary encloses no lot.

Cause. A site { boundary … } ring has fewer than 3 effective vertices once duplicate and collinear points are removed, so there is no lot to draw a property line round or to report an area for.

Fix. Give the boundary at least 3 corners that are not all on one line.

site { street north
  boundary (0,0) (10000,0) }   # error: two points is not a lot

E_SITE_BOUNDARY_SELF_INTERSECT

error — The site boundary crosses itself.

Cause. The vertices of a site { boundary … } describe a ring whose edges intersect, so it encloses no single lot and describe --json's site.lot_area_m2 would have no honest value. Usually two vertices in the wrong order.

Fix. Reorder the vertices so the boundary walks the lot line once without crossing back over itself.

site { street north
  boundary (0,0) (10000,10000) (10000,0) (0,10000) }   # error: a bow-tie

E_SITE_DUP

error — Two site blocks in one plan.

Cause. A plan declares site more than once. axes merges when repeated because two axis lists append; two street values contradict, and silently keeping the last one would hide an authoring mistake in the very statement whose job is to be the single source of orientation.

Fix. Delete one of the blocks, or merge their fields into a single site { … }. The first block is the one that takes effect.

plan "H" {
  units mm
  site { street south }
  site { street north }   # error: site already declared
}

E_SITE_NO_STREET

error — A site block declares no street.

Cause. street is the only required field of site: every derived name (back, and the three _side names) is a function of it, so a site without one derives nothing at all. Refusing beats defaulting — there is no direction a building's frontage faces by default.

Fix. Add street north, south, east or west inside the block. hemisphere is the optional field (it defaults to north).

plan "H" {
  units mm
  site { hemisphere south }   # error: no street
}

E_STAIR_WIDTH

error — Stair flight width is outside the footprint.

Cause. A stair's optional width is the FLIGHT width measured across the run, so it has to be positive and no wider than the footprint's cross-axis extent (the short side — the flight always runs along the long one). This value is not.

Fix. Drop width to fill the footprint, or give a value between 0 and the footprint's short side.

stair id=s at (0,0) size 900x2600 dir up width 1200   # error: cross extent is 900

E_STRIP_NEST

error — Illegal strip nesting.

Cause. A strip block appears inside a component, a control-flow block, or another strip. Strips place rooms and are only legal as direct plan-level statements.

Fix. Move the strip to the plan body, alongside the other elements.

component c() { strip right at (0,0) gap 0 { … } }   # error: nested strip

E_STRIP_SIZE

error — Room in a strip is missing a size.

Cause. A room inside a strip { … } gives no main-axis extent, or gives none while the strip supplies no cross-axis height/width for it to inherit — so its rectangle is undetermined.

Fix. Give the room a size <main> (main-axis extent) plus either a strip height/width or its own size <main>x<cross>.

strip right at (0,0) gap 100 { room size }   # error: no extent

E_TYPE

error — Type mismatch.

Cause. A value was used where another type was required (e.g. a string where a number is expected, or a non-array in for).

Fix. Convert or supply the expected type.

room at (0,0) size "big" x 10   # error: size needs numbers

E_UNKNOWN_COMPONENT

error — Unknown component.

Cause. An instance calls a component name that is not defined or imported.

Fix. Define the component, import it, or fix the name (see the suggestion hint).

sofa(0, 0)   # error if no `component sofa` is in scope

E_UNKNOWN_FN

error — Unknown function.

Cause. A call uses a name that is neither a built-in nor a value-function in scope.

Fix. Define it with let f(…) = …, or fix the name.

let x = frobnicate(2)   # error

E_UNKNOWN_REF

error — Unknown reference.

Cause. An expression references a name that is not bound in scope.

Fix. Declare it with let, pass it as a parameter, or fix the typo.

let x = y + 1   # error if `y` is undefined

E_VERT_SIZE

error — Vertical circulation must have a positive size.

Cause. A stair, elevator or escalator footprint's width or height evaluated to zero or a negative number, so there is no run to draw.

Fix. Give it a positive size W x H — the footprint the run occupies on this storey.

stair id=s at (0,0) size 900x0 dir up   # error: zero depth

E_VOID_SIZE

error — A floor void must have a positive size.

Cause. A void's width or height evaluated to zero or a negative number, so there is no opening in the floor plate to draw or to route circulation around.

Fix. Give it a positive size W x H — the hole's extent in plan.

void id=well at (2000,1000) size 0x3000   # error: zero width

E_WALL_THICKNESS

error — Wall must have a positive thickness.

Cause. A wall's thickness evaluated to zero or a negative number.

Fix. Give the wall a positive thickness.

wall exterior thickness 0 { (0,0) (1,0) }   # error

E_WHILE_LIMIT

errorwhile exceeded its iteration cap.

Cause. A while ran more times than the safety cap allows (usually a condition that never becomes false).

Fix. Ensure the loop body updates a binding so the condition eventually fails.

let i = 0
while i < 1 { column at (0,0) size 1x1 }   # error: i never changes

E_WINDOW_WIDTH

error — Window must have a positive width.

Cause. A window's width evaluated to zero or a negative number.

Fix. Give the window a positive width.

window at (0,0) width 0   # error

W_ALIAS_MATCH

warning — A room's use was inferred from an indirect alias, not stated.

Cause. A room has no authored uses, and its function was guessed from its label via a non-canonical alias (an indirect term like powder → WC, foyer → entry) rather than a direct word (wc, entrance). The guess is reasonable but the intent is implicit, so a reader (or agent) cannot tell the classification was assumed.

Fix. Add an explicit uses … to the room stating the inferred function — the machine-applicable fix inserts it for you. This pins the classification without changing the room's describe() type.

room at (0,0) size 2000x1500 label "Powder"   # warning: WC inferred from the alias "powder"; add `uses wc`

W_BALCONY_NO_DOOR

warning — A balcony with no way onto it.

Cause. An outdoor balcony has no door and no window within one wall thickness of any of its edges, so the drawing shows a slab that cannot be reached. A window counts as well as a door, because a full-height window is a normal way onto a balcony.

Fix. Add a door (or a full-height window) on the wall the balcony hangs off — the usual fix — or move the balcony to the facade that already has one.

outdoor balcony at (2000,7200) size 4000x1600   # warning: no opening within reach

W_BATH_VIA_BEDROOM

warning — Bathroom is reachable only through a bedroom.

Cause. Every door path from the entrance to this bathroom/WC passes through a bedroom. That is fine for a private en-suite, but a dwelling's main bathroom should open off circulation (a hall or living space), not a bedroom.

Fix. Add a door connecting the bathroom to a hall/living space, or route circulation so it is not reached only via a bedroom.

door id=d_bath at (5200,4000) width 800 wall partition   # lint: bath only off the bedroom

W_BEDROOM_NO_WINDOW

warning — Bedroom has no window.

Cause. A room labelled as a bedroom has no window on its perimeter (natural light / egress).

Fix. Add a window on an exterior wall of the room.

room at (0,0) size 3000x4000 label "Bedroom"   # lint: no window

W_CIRCUITOUS_PATH

warning — A room is reached by a very roundabout path.

Cause. The walking distance from the entrance to a room is many times its straight-line distance — the room is reachable but only by a circuitous route (e.g. all the way around the plan). A coarse circulation fact (ADR 0008); the default ratio is generous so a normal tucked-away room does not trip it.

Fix. Add a more direct connection — a door or a hall — so the room is not reached the long way round.

room id=bed at (0,0) size 3000x3000 label "Bed"   # only door is on the far side, forcing a long detour

W_DIM_INSIDE

warning — A hand-written dimension line lands inside the building.

Cause. A dim's line is drawn at offset along the LEFT normal of from→to, so the ENDPOINT ORDER chooses which side it lands on. This dimension's line (not its witness lines) falls inside the room-extents bounding box, where it crosses room labels, furniture and poché instead of reading in the page margin. Almost always the endpoints are simply the wrong way round. Advisory: an interior dimension you actually want (a clear width inside a room) is legitimate — reverse it or leave the warning.

Fix. Swap the two endpoints — the machine-applicable fix does it for you, but only when the swap actually moves the line out. Swapping mirrors the line across the segment being measured (negating the offset does the same thing), so it reaches the outside only when that segment is at the building's edge. A dimension whose measured run cuts THROUGH the plan reads inside either way and carries no automatic fix: measure along a facade instead, or raise the offset until the line clears the building.

dim (0,6000)->(7000,6000) offset -500 text "7000"   # warning: the -500 offset pulls the line back inside

W_DIM_NO_WALL

warning — A dim faces/dim clear endpoint has no wall to measure to.

Cause. The endpoint-projection forms push each endpoint onto the FACE of the wall the measurement runs into, found as the nearest wall segment perpendicular to the dimension's own direction. One (or both) endpoints has no such wall within tolerance — the point is off the wall centerline, the wall is angled, or the plan has no wall there — so there is no face to project onto and the written point is measured as-is.

Fix. Put the endpoint on the centerline of the wall the dimension runs into (the room-rectangle corner coordinate), or drop the faces/clear keyword and write the face coordinate yourself.

wall exterior thickness 200 { (0,0) (5000,0) (5000,4000) (0,4000) close }
dim faces (0,9000)->(5000,9000) offset 600   # warning: nothing to project onto at y9000

W_DIM_OVERLAP

warning — Two hand-written dimensions are drawn on top of each other.

Cause. Two dim statements measuring PARALLEL runs land in the same chain tier: their drawn bands — the dimension line, its station ticks, and the length text riding above the line — intersect, so on paper one reads through the other. ArchLang never re-staggers a hand-written dimension (the author's offset IS the tier control — ADR 0005, no invisible architect), so the collision is reported rather than silently laid out. Adjacent members of one chain that merely SHARE a station tick are not a collision and never warn, and two dims generated by one for are skipped — they share an offset expression, so no bump could separate them.

Fix. Move one of them out a tier: raise the magnitude of its offset (keeping its sign, which is the side it reads on). The machine-applicable fix computes the smallest whole number of chain tiers that clears the other dimension's line and text.

dim (0,-100)->(7000,-100) offset -300 text "7000"
dim (0,-100)->(4000,-100) offset -300 text "4000"   # warning: both in the same tier

W_DOOR_CLEARANCE

warning — Door is narrower than the minimum clear width.

Cause. A door's width is below the configured minimum passable width (default 700 mm).

Fix. Widen the door to at least the minimum clear width.

door at (0,0) width 500 wall exterior   # lint: under 700 mm

W_DOOR_NEAR_CORNER

warning — A door leaves less wall between its jamb and a corner than the wall is thick.

Cause. The nib of wall between a door's jamb and the corner its host wall turns at is shorter, along the run, than the wall is thick across it. The drawing is correct — the nib IS drawn, and mitred into the neighbouring run — so this is a fact about the plan, not a rendering fault; it was first mis-diagnosed as one during the v1.30 joinery review before it was measured. At page scale such a sliver stops reading as wall continuing to the corner and reads as a chamfer on the corner, and its returned face has nowhere to carry the frame and architrave a jamb is fixed to. The warning states the nib required, the nib measured, and the shortfall. The threshold is the wall's own thicknessminCornerNibRatio in the lint ruleset, default 1.0): it is the only length in the drawing intrinsic to the wall being measured, so the rule needs no new absolute constant and scales by itself — a 100 mm partition asks for 100 mm, a 400 mm shell for 400 — and it is the dimension the defect is about. Unlike W_POCKET_RUN the threshold is one-limbed, because both sides of the comparison belong to the same wall and there is no narrow-door pathology to guard against. What counts as a corner: the host segment's run must END at that point and the wall must go somewhere else from it, so a wall's free end, a redundant collinear vertex, a partition teeing into a wall that carries straight past it, and a TANGENT arc/straight hand-over are all excluded — nothing is mitred at any of them. On a curve the nib is an arc length, not a chord, measured at the wall's centreline radius from the radial jambs, in closed form (nothing tessellates, so the number cannot move with a facet count). Kind-independent: a jamb is a jamb whether the leaf swings, slides, folds or parks overhead. Scoped to doors deliberately — a window nib is a different detail with no frame to hang.

Fix. Move the door further from the corner by the shortfall the warning quotes (on <wall> at <pos> measures along the run, so the position is the one number to change), or lengthen the wall past the door so the corner moves away from the jamb instead. There is no machine-applicable fix: every remedy rewrites a number the author chose. Narrowing the leaf would also close the gap and is deliberately NOT offered — rewriting the width you asked for to satisfy a checker is the constraint-laundering pattern this project rules out, and it heads toward W_DOOR_CLEARANCE.

wall w1 thickness 250 { (0,0) (5000,0) (5000,4000) }
door on w1 at 4400 width 900   # lint: a 150 mm nib on a 250 mm wall

W_DOOR_OFF_WALL

warning — Door does not lie on any wall.

Cause. A door's position is not within tolerance of any wall segment, so it has no host.

Fix. Move the door onto a wall, or name its host with wall <id|category>. The diagnostic points at the nearest wall.

door at (9999,9999) width 900   # warning: not on a wall

W_DOORWAY_BLOCKED

warning — A doorway's landing is blocked.

Cause. A piece of furniture/fixture sits in the clear landing space immediately on either side of a door opening, so you cannot pass through the doorway even when the leaf is open. This is the approach path, distinct from the leaf's swing arc (W_SWING_OBSTRUCTED). The warning states the landing depth required, the depth actually left, and the shortfall.

Fix. Move the obstruction clear of the opening by the shortfall the warning quotes (arch repair computes the smallest clearing shift), shrink it by that much on the axis facing the door, or move the door along its wall so its landing misses it.

door at (6000,3000) width 800
furniture wc at (5800,3050) size 700x400   # lint: WC blocks the doorway

W_DRAWING_OVERFLOW

warning — The whole drawing does not fit the declared paper, even though the building does.

Cause. Same ruler as W_SCALE_OVERFLOW, different subject. That rule measures the BUILDING's outer-face extent against the sheet minus its margins, dimension bands, title block and margin tables. This one measures everything the plan draws against that same area — and a plan draws more than its building: outdoor ground, a fence, a site … boundary, a roof eaves line, a fixture set down outside the shell. None of that is in the building's extent, so none of it can make the fit test say no, and sheet.fits stays true while the sheet cannot hold the drawing. The two are mutually exclusive by design: the drawn extent CONTAINS the building, so when the building itself overflows you get W_SCALE_OVERFLOW instead and this would only repeat it. The warning quotes the whole drawing's extent, the drawing area it is measured against, and the overflow on each axis — a millimetre of eaves and a 40 m yard want different answers. It does not claim the page grows: nothing is clipped, the reserved sheet margin gives way first, and only a large overrun pushes the page past the paper. describe().sheet.drawing_fits is this fact; scene.sheet.page is the page that actually came out. Advisory: a site plan you intend to issue oversize, trim or tile is legitimate.

Fix. Move up a paper size or pick a coarser scale — both also shrink the building, so check the drawing still reads — or draw less ground. There is deliberately NO machine fix: every remedy rewrites a decision the author made, and unlike a building overflow there is no defensible default, since re-scaling shrinks a building that was already sized correctly for the sheet (ADR 0005).

paper A4 portrait
scale 1:100
outdoor lawn at (0,3500) size 4000x40000 label "Yard"   # warning on a 4 m cottage: the yard is 40 m long

W_DUP_ACC_METADATA

warning — Duplicate accTitle/accDescr.

Cause. A plan declares accTitle (or accDescr) more than once. Only one of each applies, so the last value silently wins.

Fix. Keep a single accTitle and a single accDescr; delete the extra line(s).

accTitle "A"
accTitle "B"   # warning: "A" is discarded

W_EMPTY_PLAN

warning — Empty plan.

Cause. The plan resolved to no drawable elements.

Fix. Add at least one element (wall, room, …).

plan "Empty" { units mm }   # warning

W_FIXTURE_BACK_TO_ROOM

warning — A fixture stands against a wall but faces the wrong way.

Cause. A fixture whose symbol has a distinct back — a plumbed one (a WC's cistern, a basin's tap, a counter's nosing) or a piece of furniture that simply has a front (a bed's headboard, a wardrobe's door line, a bookshelf's open face) — is touching a wall, but its back is turned to the room instead of to that wall: the drawing shows the WC's tank, or the headboard, sticking into the floor space. Position right, quarter-turn wrong: fixture symbols are drawn with their back on the TOP edge, so rotate is what aims them (0 = back to the north, 90 = east, 180 = south, 270 = west). A rotation-symmetric symbol (a shower tray, a round stool) never trips this, nor does arranged seating whose back to the room is a legitimate layout. A fixture that touches no wall at all is W_FIXTURE_FLOATING instead — and only where the piece genuinely needs one for services, which furniture does not.

Fix. Add the rotate that puts the back on the walled edge — the machine-applicable fix inserts it when exactly one edge is walled. Better still, place the piece with against wall <id> or in <room> anchor <edge> and let the rotation be derived.

furniture wc at (5200,5200) size 400x700   # warning: south wall behind it, cistern facing north

W_FIXTURE_FLOATING

warning — A plumbing/kitchen fixture is not against a wall.

Cause. A fixture that conventionally needs a wall behind it (WC, basin, shower, sink, counter, stove, fridge…) sits with no wall backing any edge — it appears to float in the middle of the room.

Fix. Move the fixture so one edge is against a wall (supply/waste/venting runs in the wall), or remove it.

furniture wc at (3000,3000) size 400x700   # lint: no wall behind it

W_FIXTURE_WRONG_ROOM

warning — Fixture is not inside its declared room.

Cause. A furniture item declared in <roomId> has part of its FOOTPRINT off that room's floor, so it is drawn partly (or mostly) in the wrong space. A 100 mm overhang is allowed on every side, because a room's outline runs down wall centrelines and a piece pushed against a room edge legitimately shares that band. Measured against the room's true floor, so a polygon or circle room is judged by its own shape and not by a bounding box.

Fix. Move the fixture inside the named room, or correct the in <roomId>.

furniture wc at (100,100) size 400x700 in bath   # lint: not inside "bath"

W_FURN_CLEARANCE

warning — A fixture's use-space is blocked.

Cause. The activity clearance directly in front of a fixture (WC, basin, sink, counter, stove…) is intruded by a free-standing piece of furniture, so the fixture can't be used comfortably. Other plumbing/kitchen fixtures are ignored, so a compact bathroom/kitchen run does not trip this. The warning states the catalogued clearance, the depth actually left, and the shortfall.

Fix. Move or shrink the obstructing furniture by the shortfall the warning quotes, turn the fixture so its front faces clear floor (its back must stay on a wall), or move the fixture to a wall run with the clearance free in front of it.

furniture stove at (0,0) size 600x600
furniture sofa at (0,650) size 2000x900   # lint: sofa blocks the stove front

W_FURNITURE_OVERLAP

warning — Two pieces of furniture overlap.

Cause. Two furniture/fixture rectangles occupy the same floor area, so they would physically collide — usually a coordinate or size mistake.

Fix. Move or resize one so they no longer intersect; leave a walkway between them.

furniture sofa at (300,300) size 2000x900
furniture bed  at (1000,500) size 1500x2000   # lint: overlaps the sofa

W_FURNITURE_WALL_COLLISION

warning — Furniture penetrates a wall.

Cause. A furniture/fixture rectangle intrudes into a wall's solid (it crosses the wall's thickness band rather than sitting flush against its face), so it would physically pass through the wall — a coordinate or size mistake. A piece merely touching the wall face is fine. Measured in the wall's own frame, so a wall at any angle is checked; a CURVED wall edge (arc) is not checked at all.

Fix. Move or resize the piece so it sits fully inside the room (against the wall face, not through it), or anchor it with against wall <id>.

furniture sofa at (350,2300) size 2000x900   # lint: crosses the partition at y3000

W_GARAGE_TOO_NARROW

warning — A garage is too narrow to park in.

Cause. A room classified as a garage (an authored uses garage, or a label the use vocabulary reads as one — "Garage", or the aliases "carport" / "parking") measures less across its short side than the cars in it need: 2700 mm of clear width per bay, which is a body plus the room to open a door on each side. A garage with no car fixture drawn is measured against ONE bay — a room you could not park in does not become sound by having no car in it — and bicycle/motorcycle do not count toward the bay total. The warning states the width required, the width the room actually has, and the shortfall. The rule declines a POLYGON room rather than measuring its bounding box: a box's short side is not a concave floor's clear width, and a measurement taken from a shape's box instead of the shape is a defect class this compiler has shipped before. It is advisory and has no machine fix: widening a room moves every wall and opening around it, which is a geometric decision the compiler does not make (ADR 0005).

Fix. Widen the room to the figure the warning quotes, park fewer cars in it, or drop the uses garage tag if the room is not one (a store that happens to be called a garage classifies as one from its label alone — an explicit uses storage overrides that).

room id=g at (0,0) size 2500x6000 label "Garage" uses garage
furniture car at (300,300) size 1800x4600 in g   # lint: 2500 mm across, one bay wants 2700

W_HATCH_SCALE

warning — Hatch scale must be positive; using 1.

Cause. A wall material scale evaluated to zero or a negative number.

Fix. Use a positive scale.

wall exterior thickness 200 material brick scale 0 { (0,0) (1,0) }

W_IMPORT_EMPTY_FILE

warning — Whole-file import binds an empty component.

Cause. import "<file>" as <name> turns a module's TOP-LEVEL drawable statements into one component, but that module's plan body has none (it may only declare components, or only level blocks — a storey is a page, so levels are dropped).

Fix. Draw in the module's plan body, or import one of its named components with import "<file>": <name>.

import "lib.arch" as lib   # warning when lib.arch only declares components

W_NO_ENTRANCE

warning — The plan has no exterior door.

Cause. The plan has rooms and an exterior wall but no door hosted on an exterior wall, so the building cannot be entered.

Fix. Add a door on an exterior wall.

wall exterior thickness 200 { (0,0) (4000,0) (4000,3000) (0,3000) close }   # lint: no way in

W_OPENING_OFF_WALL

warning — Opening does not lie on any wall.

Cause. A cased opening's position is not within tolerance of any wall segment, so it has no host.

Fix. Move the opening onto a wall, or name its host with wall <id|category>. The diagnostic points at the nearest wall.

opening at (9999,9999) width 1000   # warning: not on a wall

W_OUTDOOR_OVERLAPS_ROOM

warning — A ground surface is laid over a room's floor.

Cause. An outdoor surface's extent overlaps the floor of a room by more than a shared edge. Almost always a coordinate slip — a terrace written from the wrong corner, or a lawn given the building's own extent. It matters because ground and floor are reported in SEPARATE totals (totals.outdoor_area_m2 and totals.floor_area_m2), so the overlapping piece is counted twice by anything that adds them for a plot figure. A surface that merely touches a room along its edge — a patio flush against the house — does NOT trip this.

Fix. Move or resize the surface so it sits outside the building's rooms. If the overlap is deliberate (a covered terrace drawn under a room), the two are genuinely different things and one of them is the wrong element.

room id=liv at (0,0) size 5000x4000 label "Living"
outdoor paving at (1000,1000) size 3000x2000   # warning: on the living-room floor

W_PATH_TOO_NARROW

warning — The walk to a room squeezes below a passable width.

Cause. The widest route from the entrance into a room (or between a key pair of rooms, e.g. bedroom→bath) has an unavoidable pinch narrower than the minimum passable clear width — a too-narrow door/opening, or furniture crowding the way. The limit case is reported too: when no route reaches the room at all, the message gives the MEASURED width of the best way in that does exist (found by asking which smaller body does get there) rather than a fabricated zero, and calls the walk blocked only when there is no gap at all. A coarse fact from the circulation nav grid (ADR 0008); the number is grid-quantised, and it is the width a body passes through, not the room left over after its own clearance.

Fix. Widen the tightest door/opening on the route to at least the minimum, move the furniture pinching it, or add a second way in so the pinch is avoidable. There is no machine-applicable fix: the bottleneck is a nav-grid cell, not a named element, so nothing can be rewritten for you.

door at (4000,1500) width 600
furniture cabinet at (3600,300) size 700x1200   # lint: the way through squeezes below 700 mm

W_POCKET_RUN

warning — A pocket door has no wall to slide into.

Cause. A pocket door's panel disappears into a cavity inside the host wall, so the wall must continue past the slide-side jamb by at least the door's own width plus end clearance. This measures the run from that jamb to the end of the host segment, TRUNCATED at the near edge of any other opening (a window or a second door) that falls inside it — a panel cannot slide through a window either. The warning states what the run has to be, what is actually there, and the shortfall. The threshold, and a deliberate divergence from the source it is borrowed from: the required run is width + max(50 mm, width × 5%) (pocketRunClearanceMm in the lint ruleset). The rule is modelled on planscript-rust's pocket_door_wall_run, which requires a flat width × 1.05 — but a pure ratio is wrong on narrow doors: a 700 mm pocket would ask for 35 mm of end clearance, which does not fit a real jamb and pull. We are not publishing a comparison against that project, so matching its constant buys nothing, and architectural correctness outranks reference-comparability. The two extra things this rule does that the reference does not: it subtracts intervening openings, and it carries its remedies as structured fixes rather than printed prose.

Fix. Reverse the slide (slide leftslide right) — a machine-applicable fix, emitted only after the reverse run is recomputed and proved to satisfy; move the door along its wall so the pocket lands on solid wall; or lengthen the wall. Narrowing the door is deliberately NOT offered as a fix: rewriting the author's stated width to satisfy a checker is the constraint-laundering pattern this project rules out, and it would also walk into W_DOOR_CLEARANCE.

wall w1 thickness 200 { (0,0) (3000,0) }
door pocket on w1 at 80% width 900 slide right   # lint: only ~600 mm of run

W_ROOM_DISCONNECTED

warning — Room has no door — it can't be entered.

Cause. No door lies on any of the room's walls, so there is no way into the room.

Fix. Add a door on one of the room's walls.

room id=r at (0,0) size 3000x3000   # lint: no door on its perimeter

W_ROOM_LABEL_OUTSIDE

warning — A room's explicit label anchor falls outside the room.

Cause. label "…" at (x,y) pins the label and area text at a point that is not inside the room's floor, so the text will be drawn over whatever is there instead.

Fix. Move the anchor inside the room, or drop the at (…) — automatic placement uses the rectangle's centre, the circle's centre, or a polygon's area centroid (falling back to the interior point furthest from any edge where a concave ring puts that centroid off its own floor), so it lands inside either way.

room polygon (0,0) (6000,0) (6000,6000) (0,6000) label "Hall" at (9000,9000)   # warning

W_ROOM_NO_CLEAR_PATH

warning — A room cannot be entered or crossed.

Cause. Furniture, fixtures, door swings and their clearances fill the room so densely that a person stepping through a door/opening has no clear floor path into the usable space — the room is technically reachable but physically blocked.

Fix. Open up the layout: move or shrink the furniture nearest the door so there is a continuous walkable strip from each entrance into the room.

furniture shower at (5000,3000) size 2000x2000   # lint: fills the bathroom against its only door

W_ROOM_NO_FIXTURE

warning — Bathroom or kitchen has no fixtures.

Cause. A room labelled as a bathroom or kitchen contains no plumbing/kitchen fixture (WC, basin, shower, sink, counter…), so it is drawn as an empty box.

Fix. Place the expected fixtures — e.g. import lib/fixtures.arch and add a wc, basin, shower, or kitchen_sink.

room at (4000,4000) size 3000x2000 label "Bath"   # lint: no fixtures inside

W_ROOM_NOT_ENCLOSED

warning — Bathroom is not fully enclosed.

Cause. A run of this bathroom/WC's perimeter is not backed by a wall, so it is open to the adjacent space — a privacy problem for a wet room (a partition that stops short is the usual cause).

Fix. Extend the partition so the room's perimeter is walled on all sides (a door/window in the wall is fine — only a missing wall counts).

wall partition thickness 100 { (4000,0) (4000,4000) }   # lint: stops short, bath left open

W_ROOM_NOT_EQUATOR_FACING

warning — A habitable room has windows, but none faces the equator side.

Cause. The plan declares site, so the equator-facing side is known (S in the northern hemisphere, N in the southern), and a habitable room — a bedroom, living or dining space — has at least one window with none of them on that aspect. This is a drafting heuristic, not a measured daylight outcome: it says the room's windows do not face the equator, and nothing more. A south window in Reykjavík and one in Singapore are not the same daylight, and this rule does not distinguish them (there is no sun model, latitude or date anywhere in ArchLang). The rule cannot fire at all in a plan with no site, and a room with NO window is W_BEDROOM_NO_WINDOW's report, not this one.

Fix. Move a window onto the room's equator-facing facade, or accept the aspect — an urban plot often has no equator-facing wall to spare. There is deliberately NO machine fix: the remedy is a geometric decision (which facade, which wall, what else it displaces) and the compiler does not make those (ADR 0005).

site { street north }   # equator side is S
room id=liv at (0,0) size 4000x3000 label "Living"
window on north_wall at 50% width 1200   # warning: the only window faces N

W_ROOM_OVERLAP

warning — Rooms overlap.

Cause. Two room rectangles intersect.

Fix. Adjust positions/sizes if the overlap is unintended (it is allowed).

room at (0,0) size 2000x2000
room at (1000,0) size 2000x2000   # warning

W_ROOM_TOO_SMALL

warning — Room is implausibly small.

Cause. A room's floor area is below the configured minimum (default 4 m²).

Fix. Increase its size, or merge it into an adjacent space.

room at (0,0) size 1000x1000 label "Closet"   # lint: 1 m²

W_ROOM_UNREACHABLE

warning — Room cannot be reached from the entrance.

Cause. The building has an entrance, but this room has no door/opening path back to the exterior — it is sealed off from the circulation.

Fix. Add a door or cased opening linking it (directly or through a hall) to a space that reaches the entrance.

room at (5000,0) size 3000x3000 label "Store"   # lint: no path from the entrance

W_SANITIZED_CONFIG

warning — A disallowed config value was stripped.

Cause. A theme/style value contained markup or a data: URL and was blanked for safety.

Fix. Use a plain colour/string value (no <, >, or url(data:…)).

theme { wall: "<script>" }   # warning: stripped

W_SCALE_OVERFLOW

warning — The drawing does not fit the declared paper at the declared scale.

Cause. The plan declares a paper size, so scale is operative: the building's outer-face extent has to fit the sheet minus its margins, the dims auto dimension bands, the bottom chrome band (scale bar + title block) and the margin-table row that schedule rooms / legend occupy below it. At the scale in force it does not. Your scale is NEVER silently overridden — a drawing is issued at the scale printed in its own title block — so nothing is clipped: the drawing keeps its sheet margin where it can, and the page grows past the sheet when it cannot. Note that the SHEET FURNITURE counts, not just the building: adding a schedule to a tight sheet can raise this with no change to the plan's geometry. Advisory: an oversize sheet you intend to trim or tile is legitimate.

Fix. Pick a coarser scale (a larger denominator draws the building smaller), move up a paper size, drop a margin table you can do without, or drop the scale line and let the sheet auto-fit choose the finest scale from 1:50 / 1:100 / 1:200 / 1:500.

paper A4 landscape
scale 1:50   # warning on a 20 m building: 1:100 or `paper A2` fits, or omit `scale` to auto-fit

W_STAIR_UNMATCHED

warning — A run of vertical circulation appears on only one storey.

Cause. In a multi-storey plan the ONLY thing that joins two floors is identity: a stair/elevator/escalator with the same id in two level blocks is one shaft. This id appears on exactly one storey, so it connects nothing — usually a typo in the id, or the matching run was never drawn on the floor above or below. Known limitation: a top-floor stair that genuinely goes only to a roof hatch, and a lift that stops short of a storey it passes, both trip this rule; it is advisory, so leave it.

Fix. Draw the same run with the SAME id on the neighbouring storey (each storey declares its own dirup on the lower floor, down on the upper one), or fix the id.

level 1 "G" { stair id=s at (0,0) size 900x2600 dir up }
level 2 "1" { }   # warning: "s" is on level 1 only

W_SWING_OBSTRUCTED

warning — Door swing is obstructed.

Cause. The quarter-circle a door leaf sweeps overlaps a piece of furniture/fixture or another door's swing, so the door cannot open fully. The warning states the clear radius the swing needs, what it actually has, and the shortfall.

Fix. Hang the leaf on the other jamb (hinge left|right) — a machine-applicable fix when the flipped swing is proved clear; or open it the other way (swing in|out), move the door along its wall, move the obstruction (arch repair), narrow the leaf to the width the warning quotes (never below the minimum passable width — that relocates the problem into W_DOOR_CLEARANCE), hang no swinging leaf at all (a sliding, pocket or barn door sweeps nothing, so this rule cannot apply to it), or make it a leafless opening.

door at (4000,1500) width 900 swing in   # lint: leaf sweeps onto the bed

W_SWING_ROOM_NOT_ADJACENT

warningswing into <room> names a room the door does not border.

Cause. A door's swing into <room> points the leaf toward a room, but that room does not share the door's host wall (its box does not touch the wall within tolerance), so which side it means is undefined.

Fix. Point swing into at a room the door actually opens onto, or use explicit swing in|out. The door falls back to its default swing.

door on w1 at 50% width 800 swing into faraway   # warning: not on this wall

W_UNKNOWN_MATERIAL

warning — Unknown wall material; using the default hatch.

Cause. A wall material name is not one of the known hatches.

Fix. Use a known material (e.g. brick, concrete, insulation, tile) or omit it.

wall exterior thickness 200 material marble { (0,0) (1,0) }   # warning

W_UNKNOWN_STYLE_KEY

warning — Unknown style key.

Cause. A style <kind> { … } block uses a key not valid for that element kind.

Fix. Use a valid key (e.g. fill / stroke / label, depending on the kind).

style room { nope: "#000" }   # warning

W_UNKNOWN_THEME_KEY

warning — Unknown theme key.

Cause. A theme { … } block uses a key that is not a theme property or alias.

Fix. Use a known theme key (see the language reference / hover).

theme { nope: "#000" }   # warning

W_WINDOW_OFF_WALL

warning — Window does not lie on any wall.

Cause. A window's position is not within tolerance of any wall segment, so it has no host.

Fix. Move the window onto a wall, or name its host with wall <id|category>. The diagnostic points at the nearest wall.

window at (9999,9999) width 1200   # warning: not on a wall