shadcn-ui/ui · error · RegistryMissingEnvironmentVariablesError
MISSING_ENV_VARS
MISSING_ENV_VARS
Error message
Registry "${registryName}" requires the following environment variables:
• ${v} What it means
Thrown as RegistryMissingEnvironmentVariablesError (code MISSING_ENV_VARS) by validateRegistryConfig when a registry config references environment variables via ${VAR} placeholders (in url, params, or headers) that are not available in the registry context. The context env comes from withRegistryContext or falls back to process.env.
Source
Thrown at packages/shadcn/src/registry/validator.ts:48
if (config.headers) {
Object.values(config.headers).forEach((value) => {
extractEnvVars(value).forEach((v) => vars.add(v))
})
}
}
return Array.from(vars)
}
export function validateRegistryConfig(
registryName: string,
config: z.infer<typeof registryConfigItemSchema>
): void {
const requiredVars = extractEnvVarsFromRegistryConfig(config)
const missing = requiredVars.filter((v) => !getRegistryEnvFromContext(v))
if (missing.length > 0) {
throw new RegistryMissingEnvironmentVariablesError(registryName, missing)
}
}
export function validateRegistryConfigForItems(
items: string[],
config?: Config
): void {
for (const item of items) {
if (isGitHubRegistrySource(item)) {
continue
}
buildUrlAndHeadersForRegistryItem(item, configWithDefaults(config))
}
// Clear the registry context after validation.
clearRegistryContext()
}View on GitHub (pinned to efac598707)
Solutions
- Set each variable listed in the message in your shell, .env, or .env.local before running the command.
- If running programmatically, wrap the call in withRegistryContext(callback, { env: { VAR: value } }) so the context provides the values.
- Check for typos: the placeholder name must match the env key exactly (word characters only, per the ${\w+} regex).
- Remove the placeholder from the registry config if that variable is no longer needed.
Example fix
// before — API_KEY missing
const config = { url: "https://api.x.com/r/${API_KEY}/items" }
// after
process.env.API_KEY = "secret"
// or programmatically:
withRegistryContext(() => runRegistry(), { env: { API_KEY: "secret" } }) Defensive patterns
Strategy: validation
Validate before calling
function extractEnvVars(value: string): string[] {
const vars: string[] = []
let m: RegExpExecArray | null
const re = /\${(\w+)}/g
while ((m = re.exec(value))) vars.push(m[1])
return vars
}
const required = new Set<string>()
for (const v of Object.values(config.params ?? {})) extractEnvVars(v).forEach((x) => required.add(x))
extractEnvVars(config.url).forEach((x) => required.add(x))
const missing = [...required].filter((v) => !process.env[v])
if (missing.length) throw new Error(`missing env vars: ${missing.join(", ")}`) Type guard
const hasAllEnvVars = (config, env = process.env) => {
const need = new Set<string>()
const scan = (s: string) => { const re = /\${(\w+)}/g; let m; while ((m = re.exec(s))) need.add(m[1]) }
scan(config.url); Object.values(config.params ?? {}).forEach(scan); Object.values(config.headers ?? {}).forEach(scan)
return [...need].every((v) => env[v] !== undefined)
} Try / catch
try {
validateRegistryConfig(name, config)
} catch (e) {
if (e.name === "RegistryMissingEnvironmentVariablesError") {
// e.missingVars lists what to set
}
throw e
} Prevention
- Document required env vars next to each registry config.
- Load .env before invoking shadcn (e.g. via dotenv).
- Use withRegistryContext(cb, { env }) in programmatic flows so values do not leak to process.env.
- Double-check placeholder spelling against the env key.
When it happens
Trigger: extractEnvVarsFromRegistryConfig scans the registry's url/params/headers strings for ${VAR} tokens; each token is checked with getRegistryEnvFromContext. Any token whose value is undefined (neither in the AsyncLocalStorage context env nor process.env) is collected, and if the missing list is non-empty the error is thrown.
Common situations: A private registry URL like "https://api.example.com/r/${API_KEY}/item" run without API_KEY set; CI that forgot to export the token; .env not loaded; typo in the variable name so it never matches process.env.
Related errors
- INVALID_CONFIG
- The provided cwd must match config.resolvedPaths.cwd.
- A full project config is required to resolve target aliases.
- VALIDATION_ERROR
- "${registryName}" is a built-in registry and cannot be overr
AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12).
Data as JSON: /api/errors/3d0a08f095fc97ea.
Report an issue: GitHub.