Skip to content
Component installs need the registry setup
VegaStack Design

Troubleshooting

Exact error text → root cause → fix, for every failure mode hit while running real consume tests.

Last updated

Errors below are verbatim from real runs. Find yours, apply the fix. If you hit something not listed, that's a doc bug — report it with the exact output.

Before reading further, run the setup check — it catches the most common misconfigurations, including the two silent ones below:

pnpm exec vegastack-design doctor

It also scans your own source — not node_modules, build output, or the components.json ui directory — for vocabulary the shadcn reset retired: text-h1…text-h4, text-label, text-mono-label, text-strong, text-display-*, the status *-subtle steps, --alpha-*, --opacity-*, --z-*, shadow-overlay, backdrop-blur-glass, and imports of the retired components (icon-button, segmented, progress-indicator, field-inline, floating-surface, section-header, sonner). Each compiles to nothing, so it fails the run with the file:line and the replacement. A custom property your project declares itself (--z-header: 30) is yours and is not reported.

It also warns where your code works around a part instead of using it: a Tailwind ! modifier in the className of a part imported from the ui directory (gap-0!, !p-1); a w-*, min-w-* or max-w-* class on a popover, menu, select or combobox popup (PopoverContent takes size — default, md, lg, fit — and menus size to their longest item); a hand-written <header> inside SheetContent, DrawerContent, DialogContent or AlertDialogContent in the same file (use the overlay's own header part); and an AppShellPage in an App Router page/layout file whose size differs from the route map (see Page layout). These are warnings, so a release that adds one never turns your build red; once you have fixed them, run vegastack-design doctor --strict in CI to make them failures. The scan is lexical and errs toward silence: a part re-exported through your own module, or a <header> rendered by a child component, is not seen.

Coming from 0.4.x? Most of what breaks there is not a bug — it is the shadcn reset. Work Migrating to the shadcn reset first; its section 13 lists the silent failures (a deleted token compiles to nothing and the page just looks wrong).

Install & build

Can't resolve 'tw-animate-css' in '…/node_modules/@vegastack/design'

Build error the moment preset.css is imported. Two different causes — check the second one first if you are on a current version.

Cause 1 (most likely today): no Tailwind PostCSS plugin. Without @tailwindcss/postcss configured, Tailwind's engine never runs, so the bundler's own CSS pipeline tries to resolve preset.css's @import "tw-animate-css" and fails. The error names a dependency, but the dependency is fine — nothing is missing. Under Turbopack (the Next 16 default) this fails the build; under webpack the import resolves and you get the silent variant instead (next entry). Fix: add the plugin, then rebuild.

postcss.config.mjs
const config = { plugins: { "@tailwindcss/postcss": {} } };
export default config;
pnpm add -D @tailwindcss/postcss

pnpm create next-app --tailwind writes this file for you, which is why the Quickstart never mentions it. Scaffolding by hand, adding VegaStack to an existing app, or building a monorepo app all skip that step.

Cause 2 (legacy): @vegastack/design older than 0.1.1, which marked tw-animate-css as an optional peer that pnpm never installs. Fix: pnpm update @vegastack/design (≥ 0.1.1). If you are already on a newer version, this is not your problem — see Cause 1.

Build succeeds, colours and fonts work, but no utility classes exist

The worst failure mode in the consume path, because nothing errors. p-4, flex, text-muted-foreground and every other utility do nothing, while the theme looks broadly right.

Cause: no @tailwindcss/postcss plugin (as above). The token theme is literal CSS inside preset.css, so :root/.dark custom properties land regardless — but every utility class has to be generated by Tailwind, and without the plugin Tailwind never runs. The result reads as "the design system is broken" when the design system was never invoked. Fix: the postcss.config.mjs above. Confirm it: the emitted stylesheet should contain real utility selectors, not just variables.

# after a build — expect a non-trivial count, not 0
grep -o '\.[a-z][a-z0-9-]*{' .next/static/**/*.css | wc -l

Cannot find module '@vegastack/design/theme.css' (or base/utilities)

Cause: an import path outside the exports map — usually @vegastack/design-tokens/theme.css in an app that never installed the tokens package (it's transitive; pnpm-strict hides it). Fix: import the re-exports: @vegastack/design/theme.css etc. Apps should never import @vegastack/design-tokens/* directly.

Tailwind utilities exist but everything is unstyled

Cause: app/globals.css still contains create-next-app's own @import "tailwindcss" block instead of (or as well as) the preset. Fix: the file should contain exactly one entry: @import '@vegastack/design/preset.css'; — the preset imports Tailwind itself.

Registry & CLI

shadcn add → 403 (or "Failed to fetch registry")

curl -s -o /dev/null -w "%{http_code}" \
  -H "CF-Access-Client-Id: $CF_ACCESS_CLIENT_ID" \
  -H "CF-Access-Client-Secret: $CF_ACCESS_CLIENT_SECRET" \
  https://design.vegastack.com/r/registry.json
  • curl 403 too → the values are wrong: expired token, or the classic header-name-in-value mistake (CF-Access-Client-Id: abc… stored as the value). See Registry access & auth.
  • curl 200 but the CLI fails → the CLI isn't seeing your env: .env.local not in the directory you're running from, or the shell doesn't export the vars. Run from the project root; check components.json uses ${CF_ACCESS_CLIENT_ID} placeholder syntax exactly.

Component installed but looks/behaves wrong (Radix imports inside)

Cause: a bare shadcn add dialog — without @vegastack/, you got shadcn's own Radix-based component (and possibly overwrote ours). Fix: git checkout the file, re-add with the namespace: pnpm dlx shadcn@latest add @vegastack/dialog. Grep check: grep -r "@radix-ui" components/ui/ should return nothing.

shadcn init hangs forever

Cause: the CLI is waiting on an interactive prompt (non-tty shells, CI, agents). Fix: skip init — write components.json yourself; the complete known-good file is in the Quickstart §4. Init is a convenience, not a requirement.

vegastack-design: command not found

Cause: running it bare, outside a project that has @vegastack/design installed. Fix: pnpm exec vegastack-design … inside the project (the bin ships with the package), or one-off anywhere: npx --package=@vegastack/design vegastack-design ….

Runtime

toast.add(...) does nothing — no error, no toast

The #1 report. Cause: no VegaStackProvider above the calling component (or at all). Fix: Provider setup. Related: toasts appearing twice → two Toasters mounted; pass toaster={false} to one.

Hydration warning: server class="…" didn't match client, mentions <html>

Cause: missing suppressHydrationWarning on <html> — next-themes sets the theme class pre-hydration. Fix: add the attribute (Quickstart §6). This suppresses only that one attribute's check, nothing else.

Dialog / dropdown renders under the page header

Cause: the body { isolation: isolate } stacking context from base.css isn't applied — usually a granular-import setup that skipped base.css, or a CSS layer conflict overriding isolation. Fix: import the preset (it includes base.css), or re-add body { isolation: isolate }. Never "fix" this with z-index arms races.

No focus outline anywhere when tabbing

Cause: same as above — base.css skipped. Components intentionally carry no per-component focus ring; the global :focus-visible outline is the mechanism. Fix: import the preset. This is a WCAG failure, not a cosmetic issue — treat as ship-blocking.

Not a bug: a focused text input shows no outline and no background change — its border darkens subtly instead. That is the design — a text field cannot tell mouse from keyboard, so the border (on :focus, not just keyboard focus) is the one cue for both (FOC-14's text-entry exception, MK 2026-09-27).

Tooltips each wait ~600ms even when moving across a toolbar

Cause: no provider → no shared Base UI Tooltip.Provider delay group. Fix: Provider setup.

Updates

check-updates says it "could not reach the registry"

Every registry request already gets three tries with a short, jittered backoff: a network error, a response cut off mid-read ("terminated"), a 5xx or a 429 (its Retry-After, seconds or a date, honoured up to 5 seconds) is retried before anything is reported, and item fetches run at most eight at a time. So this message means the registry was unreachable for several seconds, not a one-off blip: check the runner's network, the registry URL and its Access credentials. A 404, a 401/403 or an integrity mismatch is an answer, never retried, and fails at once.

check-updates says "No VegaStack components found" despite copied components

Cause 1 (layout): it is looking in the wrong directory. It resolves components.json's aliases.ui by stripping a leading @/, then tries that path and a src/ variant. Any layout those two guesses miss — a monorepo package, or a @/* alias mapped somewhere else through tsconfig paths — scans nothing. Fix: point it at the real directory.

vegastack-design check-updates --dir packages/ui/src/components/ui

Make that the committed form of the script, not something you type once. A drift gate scanning the wrong directory is worse than no gate — which is why --fail-on-update now exits 1 when it finds zero components, instead of passing vacuously.

Cause 2 (legacy): @vegastack/design older than 0.1.1, whose check-updates only recognized files with provenance headers — which the current shadcn CLI strips on copy-in. Fix: pnpm update @vegastack/design. Current versions identify components by filename against the registry index and compare content — no header needed.

check-updates says up to date but the registry version number is higher

Not a bug. Each component carries its own version, the release in which its content last changed. A newer design-system release that did not touch that component leaves it as it is, so there is nothing to pull.

? <name> — not in registry (renamed/removed)

The component was renamed or retired upstream. Check the Changelog for the mapping; the copy in your repo keeps working regardless (you own it) — migrate when convenient. Caveat: this status only appears for files that still carry a provenance header (older CLIs / other tooling). A headerless copy of a retired component silently drops out of the report — after a rename lands in the changelog, grep components/ui/ for the old filename yourself.

--overwrite clobbered my customizations

Expected — overwrite replaces the file. Your edits are in git: git diff HEAD~1 -- components/ui/<name>.tsx, re-apply on top, run your smoke tests. Prevention: review with --diff first, keep customizations additive, or compose in wrapper files instead of editing the copy.

For agents: prefer exact-error-text search on this page over improvising. If a fix requires credentials or accounts (tokens, npm, Cloudflare), surface to a human — never work around an auth boundary.

On this page