TDC190 | case isn't a known transform | upper, lower, capitalize, title |
TDC191 | order is neither random nor sequential | Those are the only two values |
TDC192 | An interpolation filter is unknown | See Masks & case |
TDC193 | ${{Name}} or ${{Name.field}} names nothing that was declared | It would print literally — the whole reference is checked, field and all |
TDC193 | (second meaning) anomaly_flag= on a <gen> with no anomaly= | The flag column marks which rows were made outliers, and nothing made any. Add anomaly="p", or drop the flag |
TDC194 | A typed <data> has no name | Only a named <data> becomes a column |
TDC195 | repeat isn't a count or a range | repeat="3" or repeat="1..5" (0 to 64) |
TDC196 | repeat is used on a <mix> | A mix picks one branch; it doesn't produce a list |
TDC198 | separator without repeat | It joins repeated values, so there have to be some |
TDC199 | A mask index is malformed | Indices are 0-based and ranges use .. — x[0..3], w[-1] |
TDC202 | flag is set but no <case> is marked anomaly="true" | The column would be all-negative — mark the outlier branch |
TDC203 | flag is used on a nested <mix> | Only a named env-level mix carries the answer column |
TDC204 | repeat is used on a generator that can't repeat | The message names the type |
TDC206 | each="" names no sequence | Name the list to walk |
TDC207 | each names a single-value sequence | It has to be a list — add repeat to the source |
TDC209 | A named <data> sits inside an each= line | That line produces several rows, so a column name is ambiguous |
TDC211 | weight is used on a generator other than file | Weights come from a CSV column |
TDC212 | weight without column | The weights live in a second column, which has to be named |
TDC213 | weight is combined with order | order walks the rows by position; weighting picks them by frequency |
TDC242 | anomaly or missing isn't a number in [0, 1] | Both are a SHARE of the values: anomaly="0.05", missing="0.1" |
TDC243 | anomaly on a value list with no number in it | An anomaly multiplies a number, so a list of words comes back unchanged |
TDC246 | anomaly_flag on a <gen> inside a <case> | A case body is several parts joined, so a flag on one part doesn't describe the row — put flag="NAME" on the <mix> instead |
TDC247 | step on a <gen type="date"> is not a step it can walk, or mixes a calendar unit with a fixed one | Write 15m, 1h30m, 2d, 3mo, 1y — units s, m, h, d, w, mo, y; a bare number means days |
TDC248 | step without order="sequential" on the same <gen> | Nothing walks the range — the dates are still drawn at random. Add order="sequential", or drop step |
TDC249 | weekdays names a weekday that does not exist | sun, mon, tue, wed, thu, fri, sat — a span like mon..fri or a list like sun,wed |
TDC250 | weekdays with a step of a whole number of weeks, or a calendar step | Two reasons under one code. A whole number of weeks fixes the weekday, so the filter matches every row or none. A calendar step does the opposite — 1mo walks Thursday, Sunday, Sunday, Wednesday — so which rows survive would follow the calendar rather than the config |
TDC252 | peak_at on a <gen type="timeseries"> is not a number | peak_at is the row the seasonal wave peaks on, counted like period — peak_at="182" over period="365" puts the peak at the first of July |
TDC253 | peak_at with no period on the same <gen> | A wave needs a length before it can have a highest point. Add period, or remove peak_at |
TDC251 | (warning) A percent share asks for less than one whole row | percent is an exact quota over the rows that reach it, so 10% of a five-row subset asks for half a record. Half a record cannot be emitted: the branch fires once or not at all, and the seed decides which. Raise the share, or raise count |
TDC254 | A walk that has no stride: a RANGED repeat="2..5" beside order="sequential", or a walked date with any repeat= | A fixed repeat="4" works — the row takes four values off the walk. A ranged one has no fixed number of values per row, so row 5 would start wherever rows 0 to 4 happened to leave off. A walked date carries an instant beside its text, and a row holding several dates has no single one to give of= and plus= |
TDC255 | decimals= together with include= or exclude= | Drop one. A set built by include/exclude holds whole numbers and the pick is uniform over them, so there is nothing fractional to round — the engine was quietly emitting integers |
TDC256 | A mask with no pattern — <mask> without pattern=, or ${{X|mask}} with no argument | Give it a pattern. Without one the mask keeps nothing and returns the empty string, so the column comes out blank |
TDC257 | An if= expression calls a function that is not there | Either a typo, answered with the near name, or one of sin, cos, exp, log and their kin, answered with the reason: every host language computes those slightly differently, and a comparison turns the last bit into a different row. Available today: abs, ceil, floor, max, min, round, trunc |
TDC258 | A function in an if= expression is given the wrong number of arguments | abs, ceil, floor, round and trunc take exactly one; min and max take as many as you give them |
TDC259 | A [list] sits somewhere other than the right of in | A list is a set of values to test against, so it only means something as Country in [US, CA, MX]. On its own it has no value for the condition to be |
TDC260 | at() is given something that is not a list | A repeat list reaches an expression as its joined text, so at(Items, 1) asks for the second element of a one-element list and answers with nothing. Cut it first: at(split(Items, ","), 1) |
TDC261 | at() is given an index that is not one | An index is a whole number, zero or more. Past the end is empty text on purpose — rows made by repeat="1..4" have different lengths — but -1, 1.5 and "one" are mistakes, and each of them used to produce that same blank column |
TDC262 | <gen type="stat"> does not say what (of=) or which statistic (op=), or names one that does not exist | A statistic reads another column and draws nothing of its own, so both are required. op= is one of sum, mean, median, min, max, count, stddev; decimals= is 0 to 10 |
TDC263 | ${{Name}} in an attribute that does not expand it | Interpolation reaches the text inside <data> and <gen type="template" value=>, and nowhere else — anywhere else the braces are literal characters. To make one column depend on another, read it in an if= condition, or build the value in a <compute> sequence |
TDC264 | <gen type="date" of="…"> is written wrong | An offset needs plus= (7d, 3..10d, 1..3mo, -10..-3d), written smallest bound first, in a unit step= also uses. The attributes that bound the generator's OWN draw — value, from, to, range, oldest, youngest, order, step — say nothing once of= has placed the date relative to another column, so they are refused rather than ignored. The mirror is refused too: plus= on a date with no of= has nothing to be far from |
TDC265 | <assert> has no condition | An assertion is the one construct whose whole worth is that it fails, and without that= it never can. Write the property the run must have, in the if= language, over whole-run columns |
TDC266 | <assert> has no message | says= is what a reader is told when it fires, months later, in a CI log. An expression on its own leaves them to work out what it was defending |
TDC267 | (second meaning) uniq="true" on a <sequence> wrapping a <distinct> | <distinct> repairs one record so its fields differ; uniq then rearranges the finished columns and knows nothing about which pairings the repair ruled out, so it undoes them. Keep one — or give each field its own <sequence>, wrap those in <uniq>, and put the <distinct> at env level |
TDC267 | uniq="true" together with mask=, case=, missing=, repeat=, separator= or anomaly= | A draw without replacement produces the column directly and never reaches the layer that rewrites values, so the attribute could only ever be dropped. Applying it would break the other promise: a mask maps two distinct draws onto the same characters |
TDC268 | if= on a <gen type="pool"> | A reference publishes a whole MEMBER, and a <gen> carrying if= becomes a conditional branch the pool resolver does not recognise — so no Ref.field column was registered and ${{Ref.name}} reached the output as its own literal text. Use parent= to leave rows without a member |
TDC269 | if= on a <gen> inside a <case> | A case body is several parts joined into one value, so a condition on one part has no value to fall back to. It was accepted and ignored, and the part appeared on every row — including the ones the condition excluded. Put the condition on the branch: <case if="…"> |
TDC270 | <tdc> holds a second <env> or <block> | Both are read by taking the FIRST of their kind, so a second one is discarded whole — every sequence it declares, every line it lays out — while the run finishes looking healthy. Reported on the second one |
TDC271 | percent= beside order="sequential" | Walking the list in order fixes which value each row gets, so there is no share left to apportion. The percentage was accepted and dropped: percent="98,1,1" over a hundred rows came out 34 / 33 / 33 |
TDC272 | (warning) <env local=…> names a locale with no date translations | The locale is a fine source of NAMES and ships no month names, so the dates render in English. Refused outright on <gen type="date" local=…> (TDC153) and silent here until now. Fires only when the format reads the locale — format="YYYY-MM-DD" is the same in every language |
TDC273 | a filter argument the filter cannot use | slice:5,2 ends before it starts and empties the column; slice:abc, group:abc, group:0, compact:1 and compact:99 leave the value untouched. group and compact with NO argument keep their documented defaults (3, base 36) |
TDC274 | an argument on a filter that reads none | trim, sql, upper, lower, capitalize and title are whole transforms; ${{X|trim:junk}} silently ignored the junk. Chain instead: ${{X|trim|upper}} |
TDC275 | replace with nothing to look for | ${{X|replace}} and ${{X|replace:,to}} change nothing at all. Write both parts: ${{X|replace:from,to}} |
TDC276 | a pinned pack parameter of the wrong width | An identifier with a check digit has a fixed layout, so a wider or narrower part breaks it rather than shifting it. usa.finance.aba_routing prefix="12345" aborted the run; tail="678" wrote a six-digit non-number. Only reported where the width can be PROVEN from the pack's own body |
TDC277 | decimals= with no range to round | Without value= the generator produces a digit STRING — an identifier — so there is nothing to round. <gen type="number" length="4" decimals="2"/> emitted 4566, 5773, 5192 |
TDC278 | decimals= beside length= | A fractional value has no integer width to pad to, so length= was the one discarded: value="1..9" length="3" decimals="2" emitted 3.78, 2.89 |
TDC279 | first_zero="false" the range can never satisfy | Every draw from 0..5 is one digit, so a three-wide rendering always pads. The generator redrew a hundred times per row and emitted the forbidden shape anyway: 005, 002, 003. Only reported where the range PROVES it |
TDC280 | two spellings of the same date range | value=, the from/to pair and range= say one thing, and the generator reads them in that order and stops. value="2020-05-05" from="1990-01-01" to="1990-12-31" produced 1990-05-11 and discarded the rest without a word. value="today", "now" and "birth" are spellings too |
TDC281 | a date range that ends before it starts | The draw took the min and max of the two ends, so from="2020-01-01" to="2010-01-01" produced perfectly plausible dates from a range nobody wrote. plus="10..3d" has been refused as a typo rather than swapped since it was written; this is the same typo |
TDC282 | order="sequential" on only some members of a row= link | Either give every member of the link order="sequential", or drop it — a mixed link stops reading one line per record |
TDC283 | anomaly_flag on a <gen> that is only one part of its <sequence> | The flag records which ROWS were made outliers, and a sequence built from several parts — a second <gen>, a <data> literal, or a name= that makes this gen a field — has no row-level column to put it in. Move the <gen> into a <sequence> of its own; that also gives you the value as its own column. The same reasoning as TDC246, one level out |
TDC284 | (warning) secret= written into the config, or an empty one | A key in a config travels wherever the config does — into version control with it. secret="env:TDC_HTTP_SECRET" reads it from the environment, secret="file:~/.tdc/service.key" from a file the repository does not hold. A literal is a WARNING, because a service on 127.0.0.1 for an afternoon is a real use; secret="" is an error, because signing with nothing produces a signature anyone could forge |
TDC285 | A drawing attribute whose value is not one of its words, or not a number | mode=, interp=, spread= and decimals= were read only at render time, so check called mode="banana" valid and the run then refused it — the one place check did not answer "would this run?". Allowed: `mode="signal |
TDC286 | <is_digit> or <encode> was handed <field name="_count"> or <field name="_total"> | Those two fields arrive as NUMBERS; both tags want one character of text. <is_digit> answered "no" on every row — including the rows where the count is a single digit — and check said nothing; <encode> stopped the run with "expected a single-character string", naming no file and no line, on a config check had also called valid. Compare the number with <equals> or <less_than>, wrap it in <concat> for <encode>, or put the character you mean into a <str> |
TDC287 | <equals>, <greater_than> or <less_than> was given a <str> literal that is not a number | The three comparisons work on numbers. A <str> holding digits is read as the number it spells — <equals><str v="7"/><int v="7"/></equals> is true — so only a literal that is not a number is refused. That one used to stop the run with "expected an integer in <equals>, got the string …", naming no file and no line, on a config check had called valid. Only literals are checked: what a <field> will hold is not known before the run |
TDC288 | <var> — the tag was renamed to <use> | It never declared anything: <let> binds a name and this reads it back, which is what the new name says. Without a refusal of its own the old spelling fell through to "unknown compute tag", which says the spelling is wrong and not what the right one is. The name= attribute is unchanged |
TDC289 | distinct= was given something other than true or false | The attribute has two spellings and no third meaning. Treating an unrecognised word as false would leave a config that asks for distinct values and quietly gets repeats |
TDC290 | distinct= with no repeat= | One value cannot repeat itself, so the attribute would be read and then do nothing. Add repeat="N" or repeat="A..B", or drop distinct= |
TDC291 | percent= and distinct= on the same <gen> | percent= promises exact proportions across the whole run; distinct= trades that promise away for a guarantee inside each row. Both cannot hold, so neither is silently dropped. For proportions over list LENGTHS, put them on a <mix> or <switch> outside, with repeat= on the <gen> inside |
TDC292 | repeat= under distinct= asks for more values than the list can offer | Five values cannot yield six different ones. Reported before the run where the pool is in the config (type="text", a whole-number range, a one-character symbol set); at run time where it is not (a pack file, a CSV column, a regex), since those are only read while generating |
TDC293 | <gen type="pattern"> without y_range= | A drawing has no scale of its own — the same curve leaves one tool running 0..100 and another 0..10002345345. y_range="min..max" is what those coordinates mean: it becomes the floor and ceiling of the drawing's canvas. Without it every answer would be a guess about somebody's export settings, so the attribute is required rather than assumed |
TDC294 | <gen type="formula"> without expr=, or with an expr= that does not parse, or a decimals= outside 0..10 | A formula IS its expression, so there is nothing to compute without one. The expression is the same little language as if= — see Expressions. A name inside it that is not a column declared above raises TDC240 instead, the same code running and stat use for the same rule |
TDC295 | if= on a running, stat, formula or date-offset column | These are built once, for the whole run, in declaration order — an if= asks for a value chosen row by row, and the two cannot both be true. Put the condition where the value is USED (<data if="…">), or compute the column unconditionally and branch on it afterwards |
TDC296 | A running, stat, formula or date-offset column, or a <compute>, inside <uniq> or <distinct> | A group REARRANGES finished columns until each record is unique. A drawn value means the same wherever it lands; a computed one describes the row it was computed for, so moving it makes the arithmetic wrong. Put the group around the columns this one READS and leave the computed column outside it — it follows whatever the group arranges |
TDC297 | Two readings of one file at once — read="quantile" beside weight=, row= or order="sequential"; a misspelled read=; sample= without it | weight= puts the shares in a second column, row= links several columns to one LINE, order="sequential" walks the list in order, and read="quantile" says the values ARE the distribution and a row lands anywhere on the sorted sample. Keep one reading: a countable value wants weight= and its exact quota, a measured one wants the quantile read |
TDC298 | One row= key over two different files | A link is one LINE of one file, so there is no line that belongs to both. Point every member of the link at the same src=, or give this one its own row= key |
TDC299 | (warning) uniq="true" over 100,000 rows | Keeping a promise about the finished column costs memory that follows count, on every engine — the cost belongs to the promise, not to one of them. About 250 bytes a value, measured: 2,000,000 rows cost about 477 MB, and a compound uniq measures higher still. A single drawn column pays twice, because drawing without replacement cannot be done a row at a time, so that shape also runs in memory whatever mode= asks for. It works; it is worth being deliberate about |
TDC300 | fit= that is not a band, counts down, or sits beside points=/upper=/lower= | fit="low..high" says what the drawing's own lowest and highest point become on the value axis — it is how a curve read from src= gets placed, since a file carries a shape and no units. Two numbers, smaller first; turning the drawing upside down is a different request. Beside typed points it is refused: 80 there already means 80% of y_range, so there is nothing left to place. Omit it and the drawing fills y_range |
TDC301 | (warning) A share list that leaves a declared value at 0% | A percent shorter than value is fine — what is left over goes to the positions you did not write, so value="a,b,c" percent="30,40" gives c the remaining 30. When the written shares already total 100 there is nothing left, and that value is declared and can never be drawn: percent="50,50" over 300 rows came out 150 a, 150 b, no c. A zero you write yourself — percent="50,0,50" — is taken at its word and says nothing |
TDC302 | A <distinct> or <uniq> over <gen type="pool"> references that cannot mean anything: one beside an ordinary sequence, references to two different pools, or more references than the pool has members | A group over references compares WHICH MEMBER each row took, so the members must be comparable and there must be enough of them. Each of these three used to be accepted and then do nothing at all |
TDC303 | A missing_when= that decides nothing: no condition at all, no missing= rate beside it, or a repeat= cell under it | The condition names the mechanism — missing_when="Age < 30" is MAR, missing_when="_value > 150000" is MNAR — so a written-and-blank one is a question nobody finished asking, and one with no rate has no draw to gate. A repeated cell holds several values on one row while the condition asks about one, and rather than guess which reading you meant it is refused. All three used to be accepted and quietly ignored |
TDC304 | Seasonal lists that do not line up: amplitude= or peak_at= with a different number of entries from period=, or a 0 among several periods | period="7,365" amplitude="120,400" peak_at="5,182" describes the same two waves three times over, position by position, so a length that disagrees describes no wave anybody can draw — the extra entry used to be dropped and nothing said so. A single amplitude for waves of equal height is the one shorthand. period="0" alone means "no seasonal wave"; among several it is a wave with no length beside waves that have one |
TDC305 | A noise_correlation= that cannot be honoured: outside −1..1, or with no noise= beside it | It is how much of one row's jitter carries into the next. At 1 the series would wander off and never come back — a random walk, not noise — and above 1 it grows without bound; both are refused rather than clamped. Without noise= there is nothing to correlate, so the attribute decides nothing |
TDC306 | An <assert> carrying both that= and each= | They answer different questions and are checked a different number of times: that= once, over whole-run values, and each= on every row. One tag with both leaves a reader unable to tell which of the two the sentence in says= describes. Write two assertions, each with its own says=, so a failure says which one broke |
TDC307 | distinct="true" beside order="sequential" | distinct= draws the row's values without replacement, and a walked row draws nothing — its values are decided by its position. Honouring both is impossible, and quietly ignoring one is how a config comes to claim something it never had |
TDC308 | A condition on a <gen> — if= or missing_when= — naming a column declared below it | The condition is answered while this column is being built, so a column further down does not exist yet. The two engines disagreed about what to do with that, and both answers were defensible: the in-memory engine read it as empty and the condition never held, while the streaming engine built the column on demand and the condition resolved for real. Move the <sequence> it names above this one. A condition read after the row is finished — <data if=>, <line if=>, <assert that=> — may name any column |