Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

What the compiler refuses

Every validation error carries a stable slug. This is all of them, grouped by what they protect, with the fix.

Parsing errors, and errors from the pass that looks up each node’s ports, carry no slug. They point at the exact spot in your file and say what is wrong there.

Reading a diagnostic. The slug names the rule. The message names the fix. If you find one that names the problem but not the fix, that is a bug worth reporting.

Wiring

SlugMeaning
type-mismatcha connection’s source type is not compatible with its target. The message names both.
deref-patha wire reads a key off its value (t.n = s.out.profile.wpm) that the source type does not have: the message names the keys that exist, or, when the type has no keys at all (JsonDict, a scalar), says to declare the shape on the source port or Cast first.
required-port-unmeta required input has no wire and no literal. Wire it, give it a literal, or mark it optional with ?.
unknown-source-nodethe left side of a connection names a node that does not exist in this scope.
unknown-target-nodethe right side names a node that does not exist in this scope.
unknown-source-portthe node exists; that output port does not.
unknown-target-portthe node exists; that input port does not.
double-driven-portone input has two drivers: two wires, or a wire and a literal. An input has exactly one source.
input-acceptsa driver the port does not take: a wire on a port whose accepts is ["literal"], a written value on one whose accepts is ["wire"], or a wire or a @file/@asset on a port the compiler reads to build the node. The message reads the list back.
duplicate-input-portthe same input name declared twice on one node.
duplicate-node-idtwo nodes share an id in one scope.
gate-not-booleana gate written down (either spelling) that is not true or false. A wire may carry any value; a constant is a Boolean.
undeclared-port-no-customa port was referenced that the node neither declares nor allows you to add.
value-on-outputa value was written on one of the node’s output ports. An output takes no value: a firing emits on it, and you read it as node.port.

Types

SlugMeaning
unresolved-typevara type variable was never pinned to a concrete type. Pin it with an inline signature or wire something concrete in.
must-override-unmeta MustOverride port was left unpinned. Declare its type in the inline signature.
cast-not-allowedthis Cast conversion is impossible, for example JsonDict -> Number.
config-type-mismatcha config literal’s type does not match its field.
config-null-literala config field was given null, which is not a way to say “unset”. Omit the field.
literal-out-of-rangea number literal falls outside the min/max its widget declares.
named-type-conflictone type name declared twice with different bodies. Rename one. Identical bodies are fine.

Graph shape

SlugMeaning
graph-cyclea cycle in the wire graph. Iterate with a Loop; exchange feedback over a bus.
scope-reachabilitya connection reaches across a group boundary. Children reach each other and self, nothing else.
level-too-largea warning. A level of the graph (the file, or the inside of a group or loop) holds more than fifteen items, nodes or groups. At the file’s top level the count is per connected branch (the items one wire walk reaches, plus the infra nodes it touches; an infra node written at that level joins nothing, while a group holding one is an item like any other). About six per level is what reads; group the nodes cooperating on one job, and nest groups rather than widen the level. The program still runs: this is advice about how it reads.
loop-boundary-unpaireda loop’s internal boundary nodes do not line up. This is an internal invariant; hitting it is a compiler bug worth reporting.

Triggers

SlugMeaning
trigger-in-loopa trigger inside a Loop. An entry point per iteration is meaningless.
infra-in-loopan infra node inside a Loop. Infra is provisioned once for the project, not once per item.
trigger-into-triggera trigger wired into another trigger. No phase delivers that.
trigger-into-infraa trigger wired into an infra node. Provisioning happens before any fire exists.
route-overlaptwo nodes of this program claim public addresses a single call could reach, so which one answers has no answer (cards/count against cards/{id}, on a shared method). Change one path, or give them different methods. The same question is asked again at activation, across every project of the account, because only the dispatcher knows what your other programs already serve.
duplicate-porttwo ports on the node share a name on one side, which config-derived ports are the usual way to reach. Give them different names.
config-ports-not-a-listthe config key a node derives its ports from does not hold a list.
config-entry-not-an-objectan entry of that list is not an object.
unknown-config-entry-kindan entry names a kind this node does not offer.
config-entry-without-a-portan entry does not name the port it adds.
unknown-config-entry-keyan entry carries a key its kind does not take, usually a mistyped test.
config-entry-bad-testa test carries the wrong shape of value (a number where the matched input is a String, a regex that does not compile).
duplicate-catch-alltwo entries match anything; the second could never be reached.
catch-all-not-lastan entry matches anything and is not last, so the entries after it could never be reached.

Loops

SlugMeaning
loop-unbounded-no-terminationa sequential loop with no over, no max_iters, and no self.done write. Provably infinite. Give it something to exhaust, a cap, or a stop vote.
parallel-with-carryparallel: true with a non-empty carry. Carry implies an order.
parallel-without-overparallel: true with an empty over. The count has to be known up front.
parallel-with-doneparallel: true with a self.done write anywhere in the body.
over-and-carry-overlapa port listed in both over and carry.
over-not-a-lista port in over is neither a List[T] nor a Generator[T].
over-stream-not-alonea stream in over alongside another over port. A loop iterates one stream at a time.
gather-output-must-be-nullablea gather output not typed `List[T
carry-port-type-mismatcha carry port’s inside and outside types disagree.
loop-over-unknown-portover names a port the loop does not have.
loop-carry-unknown-portcarry names a port the loop does not have.
loop-config-missing-parallelan internal invariant broke while flattening the loop. You cannot cause this from source, so hitting it is a compiler bug worth reporting.
loop-parallel-not-booleanparallel is not true or false.
loop-trim-not-booleantrim_on_mismatch is not true or false.
loop-max-iters-not-integermax_iters is not a whole number.
loop-unknown-config-fieldan unrecognised key in a loop’s config.

Streams

Every one of these enforces the same property: a stream is a live handle with one producer and one taker.

SlugMeaning
generator-multiple-consumerstwo consumers on one stream. Broadcasting is a Bus.
generator-through-groupa stream crossing a group boundary.
generator-in-containera stream inside a List or Dict.
generator-not-carriablea stream carried between loop iterations.
generator-input-must-be-requiredan optional Generator input. An unwired stream has no meaning.
generator-not-iterateda Generator input on a loop that is not the over port. A stream cannot broadcast into a body.
generator-into-generic-porta stream wired into a port whose type is a bare type variable.

Names

SlugMeaning
reserved-namea node named self, a type keyword, or another reserved word.
reserved-port-namea port named index or done on a loop. Both are implicit.

Requirements and warnings

SlugMeaning
require-one-of-unmetan @require_one_of group where nothing is satisfied.
unknown-typea warning. A declared node type is not in the project’s catalog: a typo, or the node was never built. The message names the type.
no-required-skipa warning. Every input a wire feeds on this node is optional and there is no @require_one_of, so the node runs even when everything upstream is dead. Usually not what you want; add @require_one_of. A node built from written constants alone has no upstream and never gets this.
rule-structurala node’s own declarative validation rule failed at compile time. The message is the node author’s.
rule-runtimea node’s own rule flagged something checkable only at run time. The language writes one of these itself: every access node requires a connection picked (unless its recipe declares connection_optional), with no rule in its metadata.

Where these run

There are two validation modes, and the same slugs appear in both.

Structural is what a build runs, and what the editor runs constantly while you type: it fills the Problems panel and decides whether your program compiles.

Runtime adds the rule-runtime checks on top, the ones about things only knowable once a program is about to run, such as a provider node with no connection picked. A build and the Problems panel skip those deliberately, so that a program you are still wiring up builds without squiggles. They run when the question is whether the program is ready: the editor checks them right before Run/Activate/Resync (findings land on the action bar, and nothing is sent until they are fixed), and weft validate runs this mode in the terminal.

Both read source on stdin and print JSON. --file does not open a file: it names the path the source came from, so @file and @include resolve against the right directory. A finding inside an @included file carries that file’s path (a file key in the JSON), and the terminal output prefixes it as path:line:col.