Skip to content

This page is generated from docs/error-codes.md — edit it there.

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.

89 errors · 45 warnings

CodeSeveritySummary
E_ACC_PLACEMENTerroraccTitle/accDescr used outside the plan level.
E_ARC_RADIUSerrorArc radius too small for its chord.
E_ARGCOUNTerrorComponent called with the wrong number of arguments.
E_ARITYerrorBuilt-in function called with the wrong number of arguments.
E_ASSIGN_UNDEFerrorAssignment to an undeclared name.
E_ATTACH_POS_RANGEerrorOpening attachment position is out of range.
E_ATTACH_WALL_REFerrorOpening attached to an unknown or ambiguous wall.
E_CALL_DEPTHerrorValue-function call stack too deep.
E_COLUMN_SIZEerrorColumn must have a positive size.
E_DIM_CURVE_REFerrorInvalid dim radius/dim diameter reference.
E_DIV_ZEROerrorDivision or modulo by zero.
E_DOMAINerrorMath domain error.
E_DOOR_KIND_CLAUSEerrorThat clause is not available on this kind of door.
E_DOOR_KIND_CURVEDerrorA non-hinged door kind cannot sit on a curved wall.
E_DOOR_OPEN_RANGEerroropen must be between 0 and 1.
E_DOOR_WIDTHerrorDoor must have a positive width.
E_DOTTED_DECLerrorA dotted name cannot be declared.
E_DUP_IDerrorDuplicate element id.
E_DUP_INSTANCEerrorDuplicate place … as <name> instance name.
E_FENCE_CURVEDerrorA fence cannot have a curved (arc) edge.
E_FURN_AGAINSTerrorInvalid against wall fixture placement.
E_FURN_FLUSHerrorflush on a placement that touches no edge.
E_FURN_ROOMerrorFurniture placed in an unknown room.
E_FURN_ROTATEerrorFurniture rotation must be a quarter-turn.
E_FURN_SIZEerrorFurniture must have a positive size.
E_IMPORT_BAD_SPECerrorMalformed import spec.
E_IMPORT_CONFLICTerrorImported name conflicts with an existing component.
E_IMPORT_CYCLEerrorCyclic import.
E_IMPORT_NOT_EXPORTEDerrorImported name is not exported by the module.
E_IMPORT_NOT_FOUNDerrorImport path could not be resolved.
E_IMPORT_PARSEerrorImported module has a parse error.
E_INDEXerrorArray index out of range.
E_INTENT_NO_DOORerrorThe plan has no modeled entrance, so reachable cannot hold.
E_INTENT_NO_SITEerrorAn intent asserts a SYMBOLIC window facing against a plan with no site.
E_INTENT_NO_WINDOWerrorA room the brief wants a window in has too few.
E_INTENT_NOT_ADJACENTerrorTwo rooms the brief wants adjacent share no interior door.
E_INTENT_ROOM_AREAerrorA named room's floor area is outside the brief's band.
E_INTENT_ROOM_COUNTerrorThe plan's room count does not match the brief.
E_INTENT_ROOM_MISSINGerrorA room the brief names is absent from the plan.
E_INTENT_TOTAL_AREAerrorThe plan's total floor area is outside the brief's band.
E_INTENT_UNREACHABLEerrorA room cannot be reached from the entrance through modeled doors.
E_JSON_KINDerrorUnknown element kind in plan JSON.
E_JSON_SCHEMAerrorPlan JSON does not match the schema.
E_LAYOUT_CYCLEerrorRelational room placement forms a cycle.
E_LAYOUT_REFerrorRelational placement references an unknown room.
E_LEVEL_DUPerrorTwo level blocks declare the same storey number.
E_LEVEL_MIXerrorA drawable statement sits beside level blocks.
E_LEVEL_NESTerrorlevel used inside a block or component.
E_OPENING_WIDTHerrorOpening must have a positive width.
E_OUTDOOR_POLY_DEGENERATEerrorAn outdoor ring is degenerate, or a balcony was given one.
E_OUTDOOR_POLY_SELF_INTERSECTerrorAn outdoor ring crosses itself.
E_OUTDOOR_RAILerrorA rail clause on something that is not a balcony, or an unknown edge word.
E_OUTDOOR_SIZEerrorAn outdoor surface must have a positive size.
E_PARSEerrorThe source could not be read: its SHAPE is wrong.
E_PLACE_POLYerrorA rectangle-only placement clause aimed at a polygon room.
E_PLACE_REFerrorFurniture placed in an unknown or non-absolute room.
E_PNG_DEPENDENCYerrorPNG/PDF export needs an optional dependency that is not installed.
E_RANGE_LIMITerrorRange too large.
E_RECURSIONerrorComponent recursion too deep.
E_REDEFerrorName already defined in this scope.
E_ROOF_AMBIGUOUSerrorroof overhang cannot tell which wall ring to follow.
E_ROOF_CURVEDerrorroof overhang on a wall with a curved edge.
E_ROOF_OVERHANGerrorroof overhang is zero or negative.
E_ROOF_PLACEMENTerrorroof used inside a component body.
E_ROOF_POLY_DEGENERATEerrorroof polygon outline has fewer than 3 effective vertices.
E_ROOF_SELF_INTERSECTerrorThe roof outline crosses itself.
E_ROOF_WALLerrorroof overhang … wall <id> names a wall that cannot carry a roof.
E_ROOM_ALIGNerrorUnknown relational alignment edge.
E_ROOM_ALIGN_AXISerrorRelational alignment edge belongs to the other axis.
E_ROOM_POLY_DEGENERATEerrorPolygon room has fewer than three effective vertices.
E_ROOM_POLY_SELF_INTERSECTerrorPolygon room intersects itself.
E_ROOM_RADIUSerrorCircular room needs a positive radius.
E_ROOM_SIZEerrorRoom must have a positive size.
E_SITE_BOUNDARY_DEGENERATEerrorThe site boundary encloses no lot.
E_SITE_BOUNDARY_SELF_INTERSECTerrorThe site boundary crosses itself.
E_SITE_DUPerrorTwo site blocks in one plan.
E_SITE_NO_STREETerrorA site block declares no street.
E_STAIR_WIDTHerrorStair flight width is outside the footprint.
E_STRIP_NESTerrorIllegal strip nesting.
E_STRIP_SIZEerrorRoom in a strip is missing a size.
E_TYPEerrorType mismatch.
E_UNKNOWN_COMPONENTerrorUnknown component.
E_UNKNOWN_FNerrorUnknown function.
E_UNKNOWN_REFerrorUnknown reference.
E_VERT_SIZEerrorVertical circulation must have a positive size.
E_VOID_SIZEerrorA floor void must have a positive size.
E_WALL_THICKNESSerrorWall must have a positive thickness.
E_WHILE_LIMITerrorwhile exceeded its iteration cap.
E_WINDOW_WIDTHerrorWindow must have a positive width.
W_ALIAS_MATCHwarningA room's use was inferred from an indirect alias, not stated.
W_BALCONY_NO_DOORwarningA balcony with no way onto it.
W_BATH_VIA_BEDROOMwarningBathroom is reachable only through a bedroom.
W_BEDROOM_NO_WINDOWwarningBedroom has no window.
W_CIRCUITOUS_PATHwarningA room is reached by a very roundabout path.
W_DIM_INSIDEwarningA hand-written dimension line lands inside the building.
W_DIM_NO_WALLwarningA dim faces/dim clear endpoint has no wall to measure to.
W_DIM_OVERLAPwarningTwo hand-written dimensions are drawn on top of each other.
W_DOOR_CLEARANCEwarningDoor is narrower than the minimum clear width.
W_DOOR_OFF_WALLwarningDoor does not lie on any wall.
W_DOORWAY_BLOCKEDwarningA doorway's landing is blocked.
W_DUP_ACC_METADATAwarningDuplicate accTitle/accDescr.
W_EMPTY_PLANwarningEmpty plan.
W_FIXTURE_BACK_TO_ROOMwarningA fixture stands against a wall but faces the wrong way.
W_FIXTURE_FLOATINGwarningA plumbing/kitchen fixture is not against a wall.
W_FIXTURE_WRONG_ROOMwarningFixture is not inside its declared room.
W_FURN_CLEARANCEwarningA fixture's use-space is blocked.
W_FURNITURE_OVERLAPwarningTwo pieces of furniture overlap.
W_FURNITURE_WALL_COLLISIONwarningFurniture penetrates a wall.
W_GARAGE_TOO_NARROWwarningA garage is too narrow to park in.
W_HATCH_SCALEwarningHatch scale must be positive; using 1.
W_IMPORT_EMPTY_FILEwarningWhole-file import binds an empty component.
W_NO_ENTRANCEwarningThe plan has no exterior door.
W_OPENING_OFF_WALLwarningOpening does not lie on any wall.
W_OUTDOOR_OVERLAPS_ROOMwarningA ground surface is laid over a room's floor.
W_PATH_TOO_NARROWwarningThe walk to a room squeezes below a passable width.
W_POCKET_RUNwarningA pocket door has no wall to slide into.
W_ROOM_DISCONNECTEDwarningRoom has no door — it can't be entered.
W_ROOM_LABEL_OUTSIDEwarningA room's explicit label anchor falls outside the room.
W_ROOM_NO_CLEAR_PATHwarningA room cannot be entered or crossed.
W_ROOM_NO_FIXTUREwarningBathroom or kitchen has no fixtures.
W_ROOM_NOT_ENCLOSEDwarningBathroom is not fully enclosed.
W_ROOM_NOT_EQUATOR_FACINGwarningA habitable room has windows, but none faces the equator side.
W_ROOM_OVERLAPwarningRooms overlap.
W_ROOM_TOO_SMALLwarningRoom is implausibly small.
W_ROOM_UNREACHABLEwarningRoom cannot be reached from the entrance.
W_SANITIZED_CONFIGwarningA disallowed config value was stripped.
W_SCALE_OVERFLOWwarningThe drawing does not fit the declared paper at the declared scale.
W_STAIR_UNMATCHEDwarningA run of vertical circulation appears on only one storey.
W_SWING_OBSTRUCTEDwarningDoor swing is obstructed.
W_SWING_ROOM_NOT_ADJACENTwarningswing into <room> names a room the door does not border.
W_UNKNOWN_MATERIALwarningUnknown wall material; using the default hatch.
W_UNKNOWN_STYLE_KEYwarningUnknown style key.
W_UNKNOWN_THEME_KEYwarningUnknown theme key.
W_WINDOW_OFF_WALLwarningWindow 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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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).

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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>.

arch
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.

arch
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).

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

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

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").

arch
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.

arch
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.

arch
# 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).

arch
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.

arch
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.

arch
# 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).

arch
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).

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
# 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.

arch
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.

arch
# 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).

arch
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.

arch
{ "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.

arch
{ "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.

arch
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.

arch
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.

arch
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.

arch
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.

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

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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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
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.

arch
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.

arch
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.

arch
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) ….

arch
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.

arch
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.

arch
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).

arch
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.

arch
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 ….

arch
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.

arch
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.

arch
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.

arch
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.

arch
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).

arch
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.

arch
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.

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

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.

arch
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.

arch
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.

arch
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).

arch
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.

arch
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.

arch
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>.

arch
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.

arch
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).

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

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

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.

arch
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.

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

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).

arch
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, …).

arch
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.

arch
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.

arch
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>.

arch
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.

arch
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.

arch
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>.

arch
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).

arch
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.

arch
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>.

arch
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.

arch
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.

arch
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.

arch
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. A coarse fact from the circulation nav grid (ADR 0008); the number is grid-quantised.

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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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).

arch
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).

arch
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).

arch
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.

arch
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.

arch
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:…)).

arch
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.

arch
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.

arch
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.

arch
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.

arch
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.

arch
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).

arch
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).

arch
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.

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