Skip to main content
Version: Next

Diagnostics

Swatchbook surfaces load-time and runtime problems as Diagnostic entries on Project.diagnostics. Every warning or error has a stable group (a namespaced string) and a message describing what fired and why. Diagnostics appear in three places:

  • The Design Tokens panel in Storybook, live, while you author.
  • Project.diagnostics on the loaded project, for programmatic consumers (build scripts, tests, CI checks).
  • The terminal when loadProject runs outside Storybook: preset boot, MCP server start, the docs site's build.

This page catalogs every diagnostic group the core emits, what triggers each known message, and what to check when one fires.

The diagnostic shape

interface Diagnostic {
severity: 'error' | 'warn' | 'info';
group: string;
message: string;
filename?: string;
line?: number;
}

severity follows the usual gradient. error means something downstream cannot be done correctly (e.g. an alias target that doesn't exist, so the walker has nothing to resolve to). warn means the load completed but a piece of input was dropped, partial, or structurally suspect. info is informational and rarely fires.

group is namespaced by feature area (swatchbook/<area>). It's stable across releases, so consumers can filter on it.

filename / line are present when the parser knows the authoring source location. Token-tree diagnostics usually carry them; configuration diagnostics generally don't.

swatchbook/token-graph

Graph construction and walker integrity. Fires during loadProject once the parser has produced its token map.

SeverityWhen it firesWhat to check
errorA modifier writes a token as an alias to a target path that isn't defined in any baseline or modifier. Walker has no resolution to fall back to.The alias target spelling. The set of files the resolver actually loads.
errorGraph build itself threw. The graph is empty; resolveAt() returns baseline-only values.The cause string in the message, usually a malformed token shape that escaped the parser's own validation.
warnAn alias cycle was detected. The walker returns the baseline literal at the cycle entry.The chain printed in the message; at least one link in it is the unintended loop.
warnA color token's $value has a components field that isn't a numeric array (missing, or some other type). CSS emission will fail for any context that resolves to this token.The token's $value.components field in its source. Color tokens in DTCG object form require components: [number, ...].
warnA color token's components field carries an unresolved DTCG $ref object, a JSON Pointer the upstream parser did not substitute.That the JSON Pointer resolves against the rest of the token tree. If yes, the parser version handles $ref into non-Object targets.

The two warnings about color shape (structurally invalid and Unresolved $ref) are belt-and-braces for the same emit-time failure: colorjs.io's coords.map is not a function. Both fire at load time so the panel surfaces them before any block tries to render the offending token.

swatchbook/listing

Token Listing build problems. Fires when loadProject runs the in-memory @terrazzo/plugin-token-listing build to populate listing[path]. All severities are warn: when the listing build fails, blocks fall back to raw value display rather than aborting.

When it firesWhat to check
The in-memory token-listing plugin build threw or returned an error.The included detail in the message. Common causes: a plugin in terrazzoPlugins doesn't register transforms via getTransforms, so the listing's per-platform name lookup fails.
The listing build wrote no tokens.listing.json output file.The plugin's configuration. The listing plugin needs to be installed and present in the internal plugin set.
The listing JSON had no data array.The plugin version. Format compatibility is 0.1.0-alpha.x; a major version change in the plugin's output shape can produce this.

<TokenTable> and <ColorTable> previews fall back to raw values; they remain readable, but per-platform name columns are blank.

swatchbook/css-options

config.cssOptions carries a key Swatchbook ignores. Fires when load-bearing fields are set on the soft-inert cssOptions trio (baseSelector / baseScheme / modeSelectors).

SeverityWhen it firesWhat to check
warnAny of cssOptions.baseSelector, cssOptions.baseScheme, or cssOptions.modeSelectors is set. Swatchbook drives emission through its own permutations API and ignores these.Whether the value is intentional. If the consumer's production CLI build needs these, set them on the production config and leave them off cssOptions. The Aligning with your token build guide describes the split.

A separate set of cssOptions fields (variableName, permutations, filename, skipBuild) is fully stripped before being passed to the internal plugin-css build; those don't emit a diagnostic.

swatchbook/chrome

config.chrome validation. Fires once per invalid entry; valid entries pass through.

SeverityWhen it firesWhat to check
warnconfig.chrome references an unknown role. The entry is dropped.The role name spelling. The known roles are listed in the message.
warnconfig.chrome maps a role to a target that isn't a token path or composite sub-field in any theme. The entry is dropped.The target path. Block chrome falls back to the hard-coded DEFAULT_CHROME_MAP for the dropped role.

swatchbook/disabled-axes

config.disabledAxes validation.

SeverityWhen it firesWhat to check
warndisabledAxes lists an axis name that doesn't exist on the resolved project. The entry is dropped.The axis name spelling. Check the project's axes array for the actual names.

swatchbook/presets

config.presets validation.

SeverityWhen it firesWhat to check
warnA preset references an unknown axis. The preset is dropped.The axis name spelling in the preset's axes field.
warnA preset sets an axis to a context value that isn't one of the axis's known contexts. The preset is dropped.The context name spelling. Known contexts are listed in the message.

swatchbook/default

config.default validation. Same shape as preset validation: invalid entries are tolerant-dropped to the axis's own default rather than failing the load.

SeverityWhen it firesWhat to check
warndefault references an unknown axis. The axis falls back to its own default context.The axis name spelling.
warndefault sets an axis to a context value that isn't one of its known contexts. The axis falls back to its own default context.The context name spelling. Known contexts are listed in the message.

swatchbook/resolver

Resolver-source structural problems.

SeverityWhen it firesWhat to check
warnA resolver modifier has no default and no contexts. The axis is dropped from the project's axes.The resolver file. Every modifier needs either a default field or at least one entry in contexts.

Runtime emit errors

The CSS emitter wraps any throw inside transformCSSValue with structured context. The wrapped error names the token, the active axis tuple, and the offending value, with the original error preserved as cause:

swatchbook: failed to transform token "<path>" at permutation <tuple>.
$type: <type>
$value: <serialized $value>
cause: <original error message>

The fields:

  • <path>: the token's path identifier, dot-separated.
  • <tuple>: the active axis-tuple as a JSON object. Every axis in the project appears with its context value.
  • $type: the token's DTCG $type.
  • $value: the serialized $value at this tuple, as it was when the failure happened.
  • cause: the original error message. The original error object is attached to err.cause for stack-walking.

This wrap turns colorjs.io-style tracebacks (coords.map is not a function, four frames deep in a third-party library) into a single actionable line of forensic detail. The swatchbook/token-graph load-time validators catch most malformed-shape causes before they reach emit; the wrap catches the rest.

See also