Alpha — experimental. Breaking changes ship without a deprecation cycle, and nothing here carries a stability promise yet.What is built vs. planned →

Weird things & diagnostics

Transtyle prefers surprising you loudly over failing silently. This page collects every diagnostic code and every behavior that looks wrong until you know why it’s right.

How a diagnostic is printed

Two lines, never one:

✖ TST1301 Target "bootstrp" is not configured in transtyle.config.json
  ↳ Did you mean "bootstrap"? Configured targets: bootstrap, primeng

The first line says what is wrong; the hint says what to change. They’re separate fields (message and hint) in report.json too, so editors and CI annotations can place them independently. The “What to do” column below is the same advice — the point of the hint is that you get it at the moment of failure without coming here.

Two behaviors worth knowing:

Diagnostic code reference

Code Severity Meaning What to do
TST1001 warning A token glob matched no files Check the path in tokens
TST1002 error A token file failed to parse Fix the JSON; the message includes the parser error
TST1010 error transtyle.config.json doesn’t match its schema — unknown key, wrong type, missing tokens, or a bad check.failOn/contrast.standard value Fix the flagged path; a typo’d key is an error, not silently ignored, and near-miss keys get a “did you mean” suggestion
TST1011 error A target’s options are invalid for its exporter — unknown option, wrong type, or a value outside the allowed set (e.g. an unknown shadcn era) Check the exporter’s page for its options; an exporter that takes none rejects any
TST1103 warning Token defined more than once across base layers (last wins) Make the override explicit or remove the duplicate
TST1104 error Alias cycle (full chain printed) Break the cycle
TST1105 error Dangling alias — {path} points at nothing Fix the path; check tier prefixes (option. vs semantic.)
TST1106 error Unparseable value (e.g. unsupported color syntax) Colors accept oklch(), #hex, rgb(), hsl(), and CSS named colors; lab()/lch()/hwb()/color() are not yet parsed
TST1107 warning Mode-scoped file provides a value for a token with no default value Add the token to a base layer first
TST1108 warning A mode value was overridden by a later layer Confirm the layer order is intentional
TST1109 error Mode-scoped layer targets a mode not declared in modes Declare it, or fix the typo
TST1110 error Mode-scoped layer targets more than one dimension One dimension per layer
TST1111 warning $extensions.transtyle.role.archetype isn’t brand/status/neutral The role still joins the grid regardless — fix the value, or ignore if intentional
TST1112 error color-scheme is declared (with more than one value) but isn’t the first mode dimension List it first. Only the first dimension carries light/dark polarity, so a later color-scheme would ship a dark block filled with light values — the build stops rather than emit it
TST1201 error semantic.color.primary.solid missing — the one token derivation cannot invent Author your brand color at that exact path; a bare semantic.color.primary is a different slot. Silent when an upstream error already explains the absence
TST1202 error A token in derivation.require was derived, not authored Author it, or remove it from require
TST1203 warning A role archetype has no authored .solid in a given mode Author <name>.solid for that mode, or drop the archetype extension
TST1204 info An authored or bound role’s .solid resolves to the same colour in a non-default color-scheme value as in the default one — the whole derived grid carries over unchanged Author <role>.solid for that scheme value if it should differ. Default behavior, not a mistake. With derivation.autoDark: true, the carry-over is at least classified derived in coverage — it still doesn’t compute a distinct color
TST1301 error Requested target instance isn’t in the config The hint distinguishes a typo (suggests the near name) from a real exporter you simply haven’t configured yet
TST1302 error A token declares $type but has neither $value nor child tokens Add the missing $value, or remove the leftover node
TST1304 info An $extensions namespace outside transtyle.* Nothing to fix — carried through untouched, informational only
TST1305 warning A top-level group isn’t option/semantic/component Move the tokens under the right tier, or fix the typo
TST1306 warning A token’s $value has an unrecognized $type Use a DTCG type the IR understands, or accept it’s carried opaque
TST2101 warning Contrast below the configured standard (measured ratio printed) Adjust the color, or accept the warning knowingly. When a color carried over from the default mode unchanged, the hint says so — that’s usually the real cause of a dark-mode warning

TST1303 isn’t a separate code — an alias to a non-existent path is TST1105 above; it’s part of the same “authoring mistake” family the DTCG validation pass (T10) documents together.

Aliasing a derived slot is fine and won’t raise TST1105: component.button.radius: "{semantic.radius.full}" works even though nothing authors radius.full, because such aliases resolve right after derivation. TST1105 means the target never exists — at any stage.

Surprising-but-correct behaviors

A three-token design system is valid, and a target variable just goes missing

Nothing obliges you to author a radius scale, a font stack, or a border color. If you don’t, the slots that derive from them don’t exist — and an exporter that has a binding for them emits nothing rather than a broken declaration. You’ll see the variable in report.json classed dropped, with a note naming the slot to author if you want it driven:

$btn-border-radius  dropped  nothing to bind: this design system has no
                             component.button.radius. The binding exists, its
                             source does not — author that slot (or the scale it
                             derives from) and this variable starts being driven.

The target’s own default then applies, which is what “we have nothing to say about this” should mean. check:minimal-ds compiles a three-token design system against every exporter on each CI run, asserting none of them crashes and none writes a JavaScript value into a stylesheet.

My dark-native system comes out light-first

modes.default declares your native mode; it does not reorder exporter output. Exporters bind mode names — shadcn’s structure is always :root = light, .dark = dark, because that’s what shadcn consumers expect. Your native look is intact, just addressed by name. (Found by the Cathode example, now an IR rule.)

My brand color is identical in dark mode

You didn’t author a dark value, so it falls back to the light one — by design, and surfaced as TST1204 (info) so it’s visible in the report rather than only here. The test is the resolved colour, not the token text: if you bound the role to your own vocabulary and that token carries a dark value, nothing carried over and no note is raised. Transtyle does not invent brand decisions: author primary.solid a dark-mode value (one line), or set derivation.autoDark: true so the carry-over is at least classified derived in coverage instead of authored. Either way the color itself stays the light one — autoDark doesn’t yet compute a distinct dark color, that transform is a still-open question (roadmap).

--secondary doesn’t look like my secondary color

shadcn’s --secondary is a subtle surface (think: secondary button background), not a brand-secondary. The exporter maps it from neutral.tint on purpose. Your brand secondary role exists in the IR and will map to targets that actually mean “second brand color”.

A variable is classified approximated

Three current causes: --input (shadcn distinguishes input borders; the catalog doesn’t yet); OKLCH → HSL gamut clamping in the tailwind-v3 era (the note says so); unit conversions. Approximation is information, not an error — the report exists so you can decide if you care.

Negative radius in the output

With radius.md: 0rem, shadcn’s own convention produces calc(var(--radius) - 4px) = negative. Browsers treat negative radii as invalid and render 0 — the correct result. A future check may flag it explicitly.

Contrast warning on a color I like

TST2101 prints the measured WCAG ratio. It’s a warning, not a veto — set check.failOn to decide whether your CI cares. But the number is real; the near-miss cases (4.4:1) are exactly the ones eyes don’t catch.

Two builds, byte-identical output

Not a bug — a promise. No timestamps, no randomness, sorted file loading, fixed number formatting. If two builds of the same inputs ever differ, that is a bug; please report it.