Vela reference

Diagnostics

Every diagnostic code Vela can emit, how it reaches your build or editor, and the two caveats that make some of them easy to miss.

On the compile-time path, Vela reports most of what it cannot lower rather than dropping it quietly. This page lists every code it can produce and what to do about the ones you will actually hit — and, just as usefully, marks the places where nothing is reported at all.

How diagnostics reach you

The compiler produces diagnostics. The host adapter maps them into rbxtsc’s diagnostic list, using this message format:

[@vela-rbxts/compiler] unknown-theme-key: Unknown theme key "brand-500" for background color utility in className literal.

The bracketed prefix is the phase. It is @vela-rbxts/compiler for anything the compiler found in your classes, and @vela-rbxts/rbxtsc-host for the one diagnostic the adapter synthesizes itself. Numeric codes are assigned per file as diagnosticCodeBase + index, with the base defaulting to 89000 — so the first diagnostic in a file is 89000, the second 89001, and the numbering restarts for the next file. The category comes from the diagnostic’s level and defaults to Warning.

Code table

Every code is a warning unless marked otherwise.

CodeLevelFires when
unsupported-utility-familyWarningThe token does not match any known utility family
unsupported-z-index-autoWarningz-auto
unsupported-negative-z-indexWarningThe token starts with -z-
unsupported-arbitrary-z-indexWarningz-[...]
unsupported-z-index-valueWarningz-{n} outside 0, 10, 20, 30, 40, 50
unsupported-rotation-valueWarningRotation degrees outside the supported list
unsupported-scale-valueWarningscale-{n} outside the supported list
unsupported-opacity-valueWarningOpacity is not an integer from 0 to 100
unsupported-aspect-valueWarningAspect key is not square, video, or a valid bracket value
unsupported-flex-directionWarningflex-* that is neither a direction nor a flex-item keyword
unsupported-alignment-valueWarningA justify-* or items-* value that cannot be resolved
unsupported-text-sizeWarningA text-{size} that cannot be resolved (not reachable in practice)
unsupported-font-weightWarningfont-{x} is not a known weight name
unsupported-text-alignmentWarningtext-justify, or an align-* outside top/middle/bottom
unsupported-gradient-directionWarningbg-gradient-to-{x} with a direction outside the eight
unsupported-shadow-insetWarningshadow-inner
unsupported-overflow-valueWarningoverflow-* other than hidden, clip, visible
unsupported-anchor-valueWarningorigin-{x} outside the nine origin keys
unknown-theme-keyWarningA color, radius, or spacing key is absent from the theme
unsupported-size-spacing-valueWarningA spacing value used for a size is not offset-only
unsupported-border-valueWarningA border payload on the explicit rejection list
unsupported-color-keyWarningcurrent or inherit, or transparent on a property with no transparency channel
color-missing-shadeWarningA palette family referenced without a shade, and that palette has no DEFAULT
color-invalid-shadeWarningA literal given a shade, or a palette missing that shade
classname-on-unsupported-hostWarning, build onlyclassName sits on a JSX element that is neither a supported host element nor a component
unsupported-host-utilityWarning, editor onlyThe utility is not allowed on that host element tag
tsx-parse-failedErrorThe file failed to parse, or parsed with recovered errors
tsx-emit-failedErrorCode generation failed after a successful transform
compiler-invocation-failedErrorThe native compiler call threw; synthesized by the host adapter

classname-on-unsupported-host is the one that tells you nothing happened. Vela lowers className on the eight supported host elements and on components; on anything else it leaves the attribute in the output exactly as written and warns:

Warns, and the className survives untouched
<screengui className="bg-slate-700" />

That bucket is everything neither host nor component — lowercase intrinsics Vela does not implement, such as screengui, and also namespaced tags such as <svg:rect />, which never count as components. The message names only the local part of the tag, so <svg:rect /> is reported as rect. Move the classes onto a frame inside the unsupported element, or onto a component that forwards them.

This one is build only in the opposite direction to unsupported-host-utility below: the editor surface never collects an unsupported element in the first place, so it never emits this code. You only see it when you compile.

unsupported-host-utility never appears in a build. The per-element restrictions it reports — text properties only on textlabel/textbutton/textbox, image-* only on imagelabel/imagebutton, placeholder-* only on textbox — are checked by the editor surface alone. The transform pipeline never consults them, so <frame className="text-red-500" /> compiles and emits a TextColor3 assignment on a Frame with no complaint at all. Treat this one as a lint rule you only get in the editor. It is also never raised on a component: the host element behind <Panel /> is unknown, so every utility is allowed inside its className.

The three errors are structural rather than about your classes.

The four you will actually hit

unsupported-utility-family

You wrote a class Vela does not implement. The token is dropped from the output and the element is otherwise compiled normally.

Not supported
<frame className="m-4 rounded-lg" />

rounded-lg is applied; m-4 is dropped. There is no margin in Roblox — pad the parent or use gap-* on a list layout instead. The Not implemented table lists every family in this bucket along with what to reach for.

unknown-theme-key

The class parsed fine, but the key it looked up is not in the resolved theme. The family in the message tells you which scale was searched: colors, radius, or spacing.

Fails
<frame className="rounded-huge p-0.25" />

rounded-huge fails because rounded-* is a pure theme lookup and huge is not one of the ten default radius keys — add it under theme.extend.radius or use 4xl. p-0.25 fails because the spacing fallback only accepts multiples of 0.5; use p-0.5.

The most common form of this one is subtler. A color you thought you defined in theme.extend.colors will report unknown-theme-key if your config also sets a top-level theme.colors, because that combination silently discards extend. See the callout in Configuration.

color-missing-shade

You named a palette family without a shade, and that palette has no DEFAULT to fall back on.

Fails, if your brand palette defines only 500 and 700
<frame className="bg-brand" />
Compiler output
[@vela-rbxts/compiler] color-missing-shade: Color palette "brand" for background color utility has no "DEFAULT" shade, so it requires an explicit shade such as "brand-500" in className literal.

Either write the shade — bg-brand-500 — or add a DEFAULT key to the palette in theme.extend.colors so the bare form resolves. Literal colors — black, white, and anything you define as a plain string — are always usable without a shade.

color-invalid-shade

Either you gave a literal a shade, or you asked a palette for a shade it does not have.

Fails
<frame className="bg-white-500 text-brand-400" />

bg-white-500 fails because white is a literal — write bg-white. text-brand-400 fails if your brand palette only defines 500 and 700 — add 400, or use a shade you defined. Palettes do not interpolate missing shades.

Editor-only filtering

The editor surface applies one filter the build does not: it suppresses unknown-theme-key while the text after the first - in the token is three characters or shorter. This keeps the squiggle from flashing on every keystroke as you type bg-sla on the way to bg-slate-800.

The consequence is that a genuinely wrong short key can look fine in the editor and still warn in the build. Codes other than unknown-theme-key are never filtered, so color-missing-shade on a DEFAULT-less palette shows up immediately — but a short unknown key stays hidden until you compile.

See also