Skip to content

Known limitations

What to know before building Scalar’s output. These are lasting limits, not bugs: either something the DTCG 2025.10 format can’t express, or a deliberate choice to keep the output strictly valid.

Scalar never drops anything silently. Each item below is either kept in the token’s $extensions or listed in the export report, usually both. “Lost” here means $value alone isn’t enough to rebuild the original intent; the information is still in the file.

  • Extended Collections (Figma Enterprise) aren’t exported. They’re left out and named in the report.
  • References to library variables (variables from another Figma file) can’t be resolved yet: they’re written as placeholders and counted in the report. Terrazzo stops on them; Style Dictionary reports them as broken references.

Git sync on self-hosted servers is untested

Section titled “Git sync on self-hosted servers is untested”

Sync is tested on github.com and gitlab.com. It’s built to work with self-hosted GitLab and GitHub Enterprise too (set the host in Settings), but hasn’t been tried on a real one yet. If it fails, Download ZIP still works.

Colors with a separate opacity are flattened

Section titled “Colors with a separate opacity are flattened”

A color variable that points to another color but sets its own opacity is exported as a plain color with that opacity applied. The link to the base color is not in $value; the base color and opacity are kept in $extensions under com.figma.composedColor.

  • Why: DTCG has no “this token, at a different opacity” construct. A value is either a reference or a color, never both. Figma’s own export flattens these too.
  • What it means: if the base color changes, this token doesn’t follow it until you export again.

Blur and other non-shadow effects are skipped

Section titled “Blur and other non-shadow effects are skipped”

Background blur, layer blur, noise, texture and glass effects aren’t exported, and the report names each one. Only drop and inner shadows have a DTCG type (shadow).

Italic, text case (uppercase etc.) and text decoration (underline, strikethrough) aren’t part of the typography $value. They’re kept in $extensions as com.figma.fontStyle, com.figma.textCase and com.figma.textDecoration.

  • Why: a DTCG typography value has exactly five fields (font family, size, weight, letter spacing, line height), and nothing else is allowed.
  • What it means: a standard build ignores them. To use them, read $extensions in a custom transform. The CSS font shorthand can’t carry them anyway: they need separate properties (text-transform, text-decoration, font-style).

Other Figma-only text settings (paragraph spacing and indent, list spacing, hanging punctuation, leading trim, text wrap, underline style, offset, thickness and color) follow the same rule. They’re kept in $extensions only when they differ from Figma’s defaults.

Ligatures, alternate characters and other OpenType features on a text style aren’t exported: Figma doesn’t give plugins access to them. Set them in your platform code if you need them.

Bound line height becomes a fixed multiplier

Section titled “Bound line height becomes a fixed multiplier”

A text style whose line height is bound to a variable exports its line height as a number (px ÷ font size, e.g. 28 ÷ 20 = 1.4), not as a reference. The binding is kept in $extensions["ext.scalar"].boundLineHeight, and the variable itself exports as a px dimension.

  • Why: Figma applies a bound line height as px, but a DTCG typography line height is a multiple of the font size. A reference to the 28px variable would mean 28× the font size.
  • What it means: the built style doesn’t follow the variable; change it and export again. The multiplier comes from the default mode, so if the line height or font size changes between modes, it’s wrong in the other modes. The report flags those styles. An unbound % line height avoids all of this.

Font weights bound through a text variable become numbers

Section titled “Font weights bound through a text variable become numbers”

When a text style’s weight is set through a text variable (a value like "Bold"), the typography fontWeight is the resolved number (700). The binding is kept in $extensions["ext.scalar"].boundFontStyle. A weight bound to a number variable stays a live reference.

Font-weight variables on their own stay text

Section titled “Font-weight variables on their own stay text”

A standalone font-weight variable is a text variable in Figma, so it exports as $type: string with its value as written ("Bold", "SemiBold"). Scalar doesn’t guess that "Bold" means 700. Typography tokens that use it still get the number; only the standalone token keeps the name. Map names to numbers in your build if you use these tokens directly.

A token with tokens nested under it becomes $root

Section titled “A token with tokens nested under it becomes $root”

A variable or style named like a group of others (text/warning next to text/warning/strong) is exported as that group’s $root token, and references to it read {text.warning.$root}.

  • Why: a DTCG entry can’t be both a token and a group. $root is the format’s own answer.
  • What it means: the value is unchanged; only the path gains $root. Terrazzo names it after the group (--text-warning), and so does Style Dictionary 5.7.1. Older Style Dictionary versions get the name and references wrong; see Building with Style Dictionary.
  • The official DTCG JSON schema also rejects {….$root} references, even though the format spec requires them (design-tokens/community-group#448). A validator using that schema will flag them.