Skip to main content

Error codes

Every diagnostic TDC can raise, listed by code. Look one up when a run stops and the message alone isn't enough.

How to read a diagnostic

A diagnostic carries four things. The code is the part that never changes between versions — the wording may improve, but TDC193 stays TDC193:

./run demo.tdc
error[TDC193]: "Naem" is not a declared sequence — it would be printed literally
--> demo.tdc:8:11
|
8 |     <line><data>${{Naem}}</data></line>
|           ^^^^^^^^^^^^^^^^^^^^^^
|
help: did you mean "Name"?
note: Declare it in <env>, or set a different inject= pattern if you really want the text ${{…}} in the output.
  • the code — what went wrong, stable across releases;
  • the place — file, line, and column, with the offending element underlined;
  • help: — a guess at what you meant, when the name is a near miss;
  • note: — what to do about it.

Validation runs before generation, so a config with errors produces no data at all rather than half a file. Almost every diagnostic here is an error and stops the run: if the config asked for something it wouldn't actually get, TDC refuses rather than handing back data that looks right but isn't. The exceptions are seven warnings that let the run finish: TDC136 (a malformed <map> row is skipped and the valid rows still apply), TDC171 (a pack file whose header puts it at no address), TDC200 (a memory estimate that is large but still fits), TDC216 (an expression that is always true or always false), TDC221 (a <uniq> or <distinct> group with one member, which constrains nothing), TDC231 (a <pool> nothing reads) and TDC234 (a pool over 100,000 members). Each says as much in its row below.

The numbers run roughly in the order a config is checked — structure first, then generators, then everything built on top of them — but a number is an identifier, not a classification. Use the groups below.

Document structure

CodeFires whenFix
TDC001The file has no <tdc> rootWrap everything in a single <tdc>…</tdc>
TDC002<tdc> has no <block> childAdd the <block> that describes one record's layout
TDC003Both version and v are given on <tdc>Keep one — they're aliases
TDC004The declared document version isn't a valid version numberUse a version this runtime supports, e.g. v="0.1" (a value newer than the runtime raises TDC005)
TDC005The file asks for a version newer than this runtimeUpgrade TDC, or lower the declared version
TDC010A tag other than <env> or <block> sits directly under <tdc>Move it inside one of those two
TDC013A tag is nested somewhere it isn't allowedSee Tags for what may contain what
TDC014A tag that has to hold children is written self-closingWrite <env …></env>, not <env …/> — its children would be silently dropped
TDC015A tag carries an attribute the engine doesn't readThe run stops, because the config asked for something it wouldn't get. Check the spelling — the message suggests the nearest real name
TDC020count isn't a non-negative integercount="1000"
TDC021An inject pattern has no % placeholderThe marker needs a % for the name, e.g. inject="[[%]]"

Sequences

CodeFires whenFix
TDC030A tag that requires a name doesn't have oneAdd name="…"
TDC031A sequence name starts with _That prefix is reserved for built-ins
TDC032Two sequences share a nameRename one — references to it would be ambiguous
TDC033A name collides with a built-inPick another one; built-ins always win
TDC034A parent value isn't in Parent.Value formUse the two-part form, e.g. parent="Gender.Male"
TDC035The parent sequence is declared after this oneMove the parent above it — resolution is top-down
TDC214parent= names a compound sequenceA parent is filtered by the value it produced, and a group of fields produces none
TDC036A <sequence> has no <gen> inside itA sequence needs a generator to produce anything
TDC110retired — an unnamed <gen> beside a named one now composes rather than failing
TDC111Two fields of one compound sequence share a nameRename one
TDC129A <sequence> inside a config-level tag produces nothing usable thereSee Sequences

Generators

CodeFires whenFix
TDC040A <gen> has no typeAdd type="…" — see Generators
TDC041The type is unknown, or isn't supported on an inline <gen>Check the spelling; TDC suggests the nearest name
TDC050type="text" without valueGive it the list, e.g. value="a,b,c"
TDC051A percent on a value list has more entries than the list has valuesOne percentage per value, e.g. value="a,b" with percent="70,30"
TDC052A percent entry isn't a non-negative numberEvery filled position has to be a number; an empty position splits what's left equally
TDC053The percent values don't add up to 100Adjust them to total 100, or leave a position empty to absorb the remainder
TDC060type="file" without srcPoint src at the file
TDC061The file can't be readCheck the path — it's relative to the config file — or use --data-path
TDC062column doesn't resolveUse a header name (column="email") or a 1-based index (column="2")
TDC064row is used without columnRow linking needs to know which CSV column to draw from
TDC065type="http" without srcPoint it at the service — src="http://127.0.0.1:5566/gen"
TDC066src isn't an http(s) URLUse http://… or https://…, with a host and a path
TDC067in= names nothing that was declared before itThe value sent with each row has to come from an earlier <sequence>
TDC068on_error is neither fail nor emptyfail (default) stops the run; empty blanks the cell
TDC070type="template" without valueGive it the dotted address, e.g. value="person.lastName"
TDC071The template address is unknownCheck the spelling, or install the pack that provides it
TDC072value="date.range" without range, or a type="template" parameter the pack doesn't declareAdd range="…", or check the parameter name — the message lists the ones the pack accepts
TDC073A legacy range isn't two valid datesUse YYYY.MM.DD - YYYY.MM.DD
TDC081A number range is malformedvalue="10..99"
TDC082first_zero isn't true or falseThose are the only two values
TDC083length isn't a count, a range, or a comma-separated liste.g. length="8", length="6..9", length="4,6,8"
TDC084A percent on a numeric value has more entries than the range allowsOne percentage per value
TDC085A percent entry on a number isn't a non-negative numberEvery filled position has to be a number
TDC086The percent values on a number don't add up to 100Adjust them to total 100
TDC087include/exclude without a numeric range in valueThey filter a range, so there has to be one
TDC088distribution is combined with an attribute it rules outA named distribution shapes the draw on its own
TDC089The distribution parameters are wrongSee Distributions
TDC090An attribute that has to be a number isn't oneCheck the value
TDC095type="regex" without valueThe pattern goes in value
TDC096regex_max_length isn't a positive integere.g. regex_max_length="64"
TDC097The regex doesn't parseFix the pattern — the parser's own message follows
TDC098type="symbol" is given both value and alphabet, or neitherGive exactly one: an inline set in value, or a named alphabet
TDC099The named alphabet is unknownSee Symbol
TDC128type="advanced_regex" without valueThe pattern goes in value
TDC128(second meaning) default= or if= written on a <case>A <mix> picks its case by percentage and a <switch> by the is key — neither asks a condition. For condition-driven values use a <sequence> with <gen if="…"> branches
TDC130The advanced pattern doesn't parseSee Advanced regex
TDC244type="pattern" with no points, src or upperA drawing needs a shape to read: points="0,0 1,5 2,3", a file in src, or upper/lower for a band

Expressions in if

CodeFires whenFix
TDC100The expression doesn't parseSee Output & formatting
TDC101A binary operator isn't supportedSupported: == != === !== < > <= >= && || + - * /
TDC102A unary operator isn't supportedSupported: !, -, +
TDC103The expression uses computed member accessOnly plain names are allowed
TDC215A name in an if= that no sequence hasIt reads as its own text: alone the branch always fires, compared it never does
TDC216(warning) if="Seq.Value" names a value the sequence never producesThe branch is dead. A warning, not an error: a list narrowed on purpose is a real thing to write
TDC217A template path exists, but not for the run's localeThe message names the locale; set local= on the <gen> or <env>, or pick a path your locale ships
TDC218uniq="true" on a sequence with no values of its own — <compute> reads other sequences, if= picks a branch per rowPut uniq= on the sequences it reads, or wrap them in <uniq>
TDC219A <compute> and a <gen> in the same <sequence> — one of them would be droppedMove the <compute> into its own <sequence> and read the drawn one with <field>
TDC220uniq="true" on a composed value joining two or more drawn partsThe parts have no fixed width, so a unique set of parts is not a unique string: 9+15 and 91+5 are the same three characters. Keep one drawn part, or make the widths fixed
TDC221(warning) A <uniq> or <distinct> around fewer than two <sequence>sA group constrains its members against each other, so one member constrains nothing. Add a second member, or write uniq="true" on the sequence itself

<pool>

See Coherent records.

CodeFires whenFix
TDC222A <pool> with no name, or with no countA pool is read by name and holds a fixed number of members: <pool name="Doctors" count="30">
TDC223A <pool count="…"> that is not a whole number of at least 1A pool of nothing has no member to hand out
TDC224<gen type="pool" value="X"> where no <pool name="X"> is declaredThe message lists the declared pools. Declare it in the same <env>
TDC225filter="field == X" where the two sides can never hold a common valueBoth lists are written in the config, and they do not meet — so every row is narrowed to no member at all. The message names both. Only a certain contradiction is reported here; a value that merely comes up rarely is refused at the row that draws it
TDC226filter= reads Pool.field and the pool has no such fieldThe message lists the pool's fields. An unqualified unknown name is left alone — the expression language reads a bare word as a literal
TDC229${{Ref}} where Ref draws a whole memberA member is a record, not a value. Read a field: ${{Ref.lastName}}
TDC230A <block>, a fixture tag, or another <pool> inside a <pool>A pool is a table other columns read, not something written to a file, and pools do not nest
TDC231(warning) A <pool> no <gen type="pool"> readsIt is built in full before the first row and kept in memory for the whole run, so an unread one is paid for and thrown away. Read it, or remove it
TDC232A name in filter= that is both a field of the pool and a sequenceRename one of them. Qualifying one side does not help — the other name still reads as the member's field, so the test compares a value with itself
TDC234(warning) Over 100,000 membersA pool stays in memory for the whole run — about 320 bytes a member with four fields. If you meant the number of ROWS, that is count on <env>
TDC235Over 1,000,000 membersSame cause, past the point where it is worth running. Reduce the pool, or move the number to <env count="…">
TDC236(warning) uniq="true" over 100,000 rowsDrawing without replacement means remembering what has been drawn, so the whole column stays in memory and the run cannot stream. Measured at about 250 bytes a value — 2,000,000 rows cost about 477 MB. It works; it is worth being deliberate about
TDC236A pool reads a pool declared below it, or itselfPools are built in declaration order, so a pool can only read the pools above it. Move the one it reads up. That order is also why a cycle between pools cannot be written down
TDC241Two pools declared under one nameA pool is reached by name, so two cannot share one. The second used to replace the first in silence, and the only sign was a TDC193 in the block about a field that "does not exist"

Three numbers in this range were reserved while pools were being designed and will stay unused, so the gaps are declared rather than silent:

  • TDC227filter= naming a column that does not exist. A bare word in the expression language has always been a string literal, and that is what filter="clinic == North" uses to say "northern only". A typo and a literal are the same thing written down, so the check would put an error on working configs. Where the literal is a certain mistake — no member could ever hold that value — TDC225 says so instead, without guessing.
  • TDC228${{Pool.field}} addressing a pool without going through a reference. TDC193 already reports it as a name that resolves to nothing, and a second code for the same sentence is not worth the number.
  • TDC233 — no candidate passed filter= on row N, for expressions richer than a simple equality. That refusal happens and is worth having; it just is not a diagnostic code. It compares against a value that only exists once the row is being built, so it belongs to the run, and the run's message names the row and the value that matched nobody.

Running totals

See accumulate= and <gen type="running">.

CodeFires whenFix
TDC237accumulate= on a generator with no repeat=There is no list to accumulate. Add repeat="N", or drop accumulate=. (type="running" is exempt — it accumulates down a column)
TDC238accumulate= names an operation that does not existOne of sum, min, max
TDC239<gen type="running"> does not say what (of=) or how (accumulate=) to accumulateA running total reads another column and draws nothing of its own, so both are required
TDC240of= or reset= names a column not declared aboveThe total is built from a column that already exists — the same rule parent= follows

<compute>

CodeFires whenFix
TDC180A tag inside <compute> that the compute language does not have, or a predicate written outside <test>The message names the tag. Check it against the compute reference — a predicate such as <eq> is valid only inside <test>
TDC181<current>, <current_index>, or <acc> is used outside its iteration bodyThey exist only inside a <do> (or a <reduce>'s <do>)
TDC182<var name="X"> names no enclosing <let>Wrap it in <let name="X">…</let>, or fix the name
TDC183A binary compute op has the wrong number of children<add>, <subtract> … take exactly two operands
TDC184<choose> has no <otherwise> branchAdd <otherwise> — every record needs an answer
TDC185A <let name="X"> shadows an outer binding of the same nameRename one — the inner binding would hide the outer one
TDC186<encode>: unknown encodingOne of: base36, ascii, unicode, hex, binary, octal
TDC187A predicate is missing its wrapper child<when> wants <test>, <choose> wants <then> — the message names the pair
TDC188<int v="…"> isn't a whole numberWrite a whole number; for text, use <str v="…"/>
TDC189<compute> has more than one <result>Keep a single <result> — the earlier ones would be dropped

<mix>, <switch>, fixtures

CodeFires whenFix
TDC120<mix> has no <case>A mix needs branches to pick between
TDC121A percent on a <mix>/<switch> has more entries than there are casesOne percentage per case
TDC122A percent entry on a <mix>/<switch> isn't a non-negative numberEvery filled position has to be a number
TDC123The percent values on a <mix>/<switch> don't add up to 100Adjust them to total 100
TDC124<mix> has a child that isn't a <case>Only <case> belongs there
TDC125<case> has an unknown childAllowed: <data>, <gen>, <mix>
TDC131A fixture contains a tag that fixtures don't acceptFixtures hold <line> and <data> only
TDC132A tag that doesn't belong there sits inside <line>The output block is for layout — generators live in <env>
TDC133<switch> has no onName the sequence being switched on
TDC134on names a sequence, or a field of one, that doesn't existCheck the name — the message says which half is wrong
TDC135<switch> has no entriesAdd a <map>, <case>, or <default>
TDC136(warning) A <map> row isn't KEY:VALUE — the bad row is skipped and the rest of the map still appliesOne pair per entry, separated by a colon
TDC137A <case> inside <switch> has no isis is the branch key
TDC245name on a <switch> written inside a <case>The nested form contributes a value to that branch; only an env-level <switch> becomes a column

Dates

CodeFires whenFix
TDC150Only one of from / to is givenGive both endpoints or neither
TDC151The date value doesn't parsevalue="2020-01-01..2025-12-31", "birth", "today", "now"
TDC152A format token is unknownSee the token table
TDC153local names a locale with no date dataBuilt in: en, es, ru, zh-cn
TDC154precision isn't a supported stepSee precision

While rendering

These are raised during generation rather than validation — the config is well-formed, but the combination it asks for can't be carried out.

CodeFires whenFix
TDC160row="…" is used on an inline <gen>Row linking needs a <sequence>
TDC161Weighted advanced_regex choices are used inlineExact percentages need the whole column — move it into a <sequence>
TDC162An inline counter's value or step isn't numericvalue="1" step="2"
TDC170A data-pack file can't be loadedThe message names the file — see Writing your own
TDC171(warning) A data-pack file lands at no address, so it is skippedAdd address: or locale: to its header, or move it under a locale folder
TDC200(warning) The estimated memory use is a large share of this machine's RAM — the run continuesFor very large sets, use mode="disk", which keeps memory flat
TDC201The estimated memory use is more than this machine's RAMLower count, batch the run, or use mode="disk"
Three of these cannot be reached from a config

TDC160, TDC161 and TDC162 describe an inline <gen> — one written directly inside <line> rather than in a <sequence>. Validation refuses that shape first, with TDC131 (a <gen> is not allowed inside <line>) or TDC013, so a real config never gets far enough to raise them. They are reachable only through the low-level render(parse(src).tree) export, which walks an unvalidated tree on purpose. That is also why the four ports do not have them: they compile a config into a model that has no place to put such a <gen>.

Formatting and modifiers

CodeFires whenFix
TDC190case isn't a known transformupper, lower, capitalize, title
TDC191order is neither random nor sequentialThose are the only two values
TDC192An interpolation filter is unknownSee Masks & case
TDC193${{Name}} or ${{Name.field}} names nothing that was declaredIt would print literally — the whole reference is checked, field and all
TDC194A typed <data> has no nameOnly a named <data> becomes a column
TDC195repeat isn't a count or a rangerepeat="3" or repeat="1..5" (0 to 64)
TDC196repeat is used on a <mix>A mix picks one branch; it doesn't produce a list
TDC198separator without repeatIt joins repeated values, so there have to be some
TDC199A mask index is malformedIndices are 0-based and ranges use ..x[0..3], w[-1]
TDC202flag is set but no <case> is marked anomaly="true"The column would be all-negative — mark the outlier branch
TDC203flag is used on a nested <mix>Only a named env-level mix carries the answer column
TDC204repeat is used on a generator that can't repeatThe message names the type
TDC206each="" names no sequenceName the list to walk
TDC207each names a single-value sequenceIt has to be a list — add repeat to the source
TDC209A named <data> sits inside an each= lineThat line produces several rows, so a column name is ambiguous
TDC211weight is used on a generator other than fileWeights come from a CSV column
TDC212weight without columnThe weights live in a second column, which has to be named
TDC213weight is combined with orderorder walks the rows by position; weighting picks them by frequency
TDC242anomaly or missing isn't a number in [0, 1]Both are a SHARE of the values: anomaly="0.05", missing="0.1"
TDC243anomaly on a value list with no number in itAn anomaly multiplies a number, so a list of words comes back unchanged

See also