{"record":{"id":"70208c1330c08163","repo":"shadcn-ui/ui","slug":"a-full-project-config-is-required-to-resolve-targe","errorCode":null,"errorMessage":"A full project config is required to resolve target aliases.","messagePattern":"A full project config is required to resolve target aliases\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/shadcn/src/registry/add.ts","lineNumber":86,"sourceCode":"  )\n  const env = await loadEnvFiles(cwd, {\n    processEnv: { ...process.env },\n  })\n\n  return withRegistryContext(\n    async () => {\n      const resolvedTree = await resolveRegistryTree(items, config, {\n        useCache: true,\n        requireUniversal: !parsedConfig.success,\n      })\n      if (!resolvedTree) {\n        throw new Error(\"Failed to fetch components from registry.\")\n      }\n      if (\n        !parsedConfig.success &&\n        !hasResolvedTargetAliases(resolvedTree, config)\n      ) {\n        throw new Error(\n          \"A full project config is required to resolve target aliases.\"\n        )\n      }\n\n      await addComponents(items, config, {\n        ...addComponentsOptions,\n        interactive: false,\n        overwriteCssVars:\n          options.overwriteCssVars ??\n          (parsedConfig.success ? undefined : false),\n        resolvedTree,\n      })\n    },\n    { env }\n  )\n}\n\nfunction hasResolvedTargetAliases(","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/shadcn-ui/ui/blob/efac5987074af84ece57c367c6dd83387b967022/packages/shadcn/src/registry/add.ts#L68-L104","documentation":"Plain Error thrown when the passed config did not fully parse (parsedConfig.success is false) AND hasResolvedTargetAliases returns false for the resolved tree. hasResolvedTargetAliases checks that every file in the tree whose `target` maps to a known alias key has that alias present in config.resolvedPaths. With a partial config, target aliases like `ui`, `lib`, etc. cannot be resolved, so installation would write to unknown locations.","triggerScenarios":"Calling addRegistryItems with a partial Config (no resolvedPaths for the required aliases) for items whose registry entries declare `target` fields (e.g. target: 'ui'); passing a config object that omits aliases but requesting items that need them.","commonSituations":"Embedding shadcn and passing a minimal `{ tailwind: {...} }` config while installing components that target ui/lib/hooks directories; CI scripts that skip running get-config.","solutions":["Pass a full project Config resolved via get-config (so parsedConfig.success is true and the alias check is bypassed).","If passing a partial config, ensure resolvedPaths includes every alias the requested items target (check each item's `target` field).","Run `npx shadcn@latest init` first so components.json has all aliases, then let shadcn resolve the Config itself.","Inspect the resolved tree's files[].target values to see which alias is missing."],"exampleFix":"// before — partial config, items need ui/lib aliases\naddRegistryItems(['button', 'use-toast'], {\n  config: { style: 'new-york' }\n})\n\n// after — pass a full config (resolved via get-config) including aliases\naddRegistryItems(['button', 'use-toast'], {\n  config: {\n    style: 'new-york',\n    resolvedPaths: {\n      cwd: '/app',\n      ui: '/app/src/components/ui',\n      lib: '/app/src/lib',\n      hooks: '/app/src/hooks'\n    }\n  }\n})","handlingStrategy":"validation","validationCode":"import { configSchema } from '@/src/schema'\nimport { resolveRegistryTree } from '@/src/registry/resolver'\nimport { getTargetAliasKey } from '@/src/utils/target-aliases'\n\nasync function assertTargetAliasesResolvable(items: string[], config: Partial<Config>) {\n  const parsed = configSchema.safeParse(config)\n  if (parsed.success) return // full config — alias check is bypassed\n  const tree = await resolveRegistryTree(items, config as Config, { useCache: false })\n  if (!tree) return\n  const missing = (tree.files ?? [])\n    .map(f => getTargetAliasKey(f.target))\n    .filter(k => k && !config.resolvedPaths?.[k])\n  if (missing.length) {\n    throw new Error(`Partial config missing resolvedPaths for: ${Array.from(new Set(missing)).join(', ')}`)\n  }\n}\n\nawait assertTargetAliasesResolvable(items, options.config ?? {})","typeGuard":"import { configSchema } from '@/src/schema'\n\nfunction isFullConfig(c: unknown): c is Config {\n  return configSchema.safeParse(c).success\n}","tryCatchPattern":"try {\n  await addRegistryItems(items, { config: partial })\n} catch (e) {\n  if (e instanceof Error && e.message.includes('full project config')) {\n    // re-resolve a full Config via get-config and retry\n    const full = await resolveFullConfig(cwd)\n    await addRegistryItems(items, { config: full })\n  } else throw e\n}","preventionTips":["Pass a full Config resolved via get-config when installing items with target aliases.","Inspect each item's `target` field to know which aliases are required.","Run `shadcn init` so all alias paths exist before programmatic installs."],"tags":["registry","add","config","aliases","validation"],"backgroundTag":null,"analyzedSha":"efac5987074af84ece57c367c6dd83387b967022","analyzedAt":"2026-08-12T05:00:50.218Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}