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

  1. Set each variable listed in the message in your shell, .env, or .env.local before running the command.
  2. If running programmatically, wrap the call in withRegistryContext(callback, { env: { VAR: value } }) so the context provides the values.
  3. Check for typos: the placeholder name must match the env key exactly (word characters only, per the ${\w+} regex).
  4. 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

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


AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12). Data as JSON: /api/errors/3d0a08f095fc97ea. Report an issue: GitHub.