Troubleshooting
Exact error text → root cause → fix, for every failure mode hit while building the reference starter and 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 doctorInstall & 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.
const config = { plugins: { "@tailwindcss/postcss": {} } };
export default config;pnpm add -D @tailwindcss/postcsspnpm 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 -lCannot 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.localnot in the directory you're running from, or the shell doesn't export the vars. Run from the project root; checkcomponents.jsonuses${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(...) 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 ring anywhere when tabbing
Cause: same as above — base.css skipped. Components intentionally carry no
per-component focus ring; the global :focus-visible layer is the mechanism.
Fix: import the preset. This is a WCAG failure, not a cosmetic issue — treat
as ship-blocking.
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 "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/uiMake 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. Status is by content hash, not version: the global version bumped but that component's bytes didn't change. 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.