Skip to content

Compile errors

situ fails closed: everything outside the compiled dialect, the seam, or the composition envelope is a CompileError raised at compile time (in dev, surfaced on your framework's debug page — Litestar's or Flask's; in the lint loop via tests and situ check), so problems surface as visible errors while you develop. The compiler carries 111 distinct rejection sites; the inline messages are maintained as part of the API. This page catalogs the ones you'll actually meet, with their fixes.

The seam

Message (abridged) Fix
server-sited 'x' cannot be read on the client; DB-backed state stays on the server Render it server-side (Jinja / context()), ship named row fields explicitly, or push a value with signal() from a command
cannot assign server-sited signal 'x' on the client Mutate through a command (await facade...)
cannot assign url-sited signal 'x' on the client Url state is set by navigation — use a link
refusing to compile a loop over server-sited 'x': DB iteration stays on the server Loop in context() or the facade; the template's Jinja {% for %} renders the result
await in a client position (an @event, a client body) Only a handler body may await — which makes it a server command

The dialect

Message (abridged) Fix
cannot compile expression: <NodeType> / statement not in the compiled dialect: <NodeType> Restructure into the dialect, or move the logic server-side
unknown name / unsupported call / unsupported method Only signals, row vars, and the whitelisted functions exist client-side
f-string conversion (!r) or format spec (:.2f) rejected Format server-side, or simplify
membership can't chain with comparisons Split the condition
dict keys must be string constants

Templates

Message (abridged) Fix
:each needs 'var in iterable' The binder value is row in signal
a binder/event on the :each element itself Put :each on a wrapper element
a row event other than @click/@submit Restructure; rows support click/submit
:bind on a non-Local signal Two-way binding is client state by definition
reactive element outside <header> / data-region (silently inert at runtime) Respect the two runtime rules

Composition

Message (abridged) Fix
unknown component <Tag> Register it (components= / Context.from_dir) — and run situ check in your lint loop so this fails fast
missing / extra / duplicate / unused Prop or Emit binding Match the child's declared contract exactly
Inject with no ancestor Provide Provide it on an ancestor, or thread a Prop
content given to a child that declares no <slot> Add a <slot> to the child (content would otherwise vanish)
signal declared by two components / minted-name collision Rename — flat-island names are per-tree
per-instance state inside a :each via an intermediate Fenced: give the state to the row (top-level :each) or lift it
bare prop on a nested host — use the colon form :prop= Only :/@ bindings substitute through composition levels
component placement cycle: A > B > A / self-placement Composition is a finite tree; data-driven recursion uses :each + :tree
a top-level component's <style> Only child components are CSS-scoped; move page styles to the page

declui

Message (abridged) Fix
unmapped field type Add a widget= or change the type — declui never degrades to a text box
predicate: identifier / call / node outside the grammar Stay in the predicate vocabulary
Decimal relational compare in a predicate String-valued for precision; compare equality, or model as int/float
@action gate referencing a date field, or calling a function The server-row grammar excludes them
model field named value / editing; action named reset Reserved names
a local variable shadowing a field in a sync action Rename the local — it would silently write the signal
server mount passed screens= / rows= / choices=; service_type without context The fail-closed mount rules

The philosophy

A bounded compiler earns its keep by where it stops. If an error message doesn't point at the fix, treat that as a bug and report the message text.