{"record":{"id":"fff193ffafa3b508","repo":"nexu-io/open-design","slug":"bad-request-fff193","errorCode":"BAD_REQUEST","errorMessage":"local project path must be a directory","messagePattern":"local project path must be a directory","errorType":"validation","errorClass":"LocalDesignSystemImportError","httpStatus":400,"severity":"error","filePath":"apps/daemon/src/design-systems/import.ts","lineNumber":127,"sourceCode":"  'node_modules',\n  'out',\n  'target',\n]);\n\nconst STYLE_EXTENSIONS = new Set(['.css', '.scss', '.sass', '.less']);\nconst COMPONENT_EXTENSIONS = new Set(['.tsx', '.jsx', '.vue', '.svelte']);\nconst ASSET_EXTENSIONS = new Set(['.svg', '.png', '.jpg', '.jpeg', '.webp', '.ico']);\nconst FONT_EXTENSIONS = new Set(['.woff', '.woff2', '.ttf', '.otf']);\nconst COMPONENT_NAMES = ['Button', 'Input', 'Card', 'Nav', 'Navbar', 'Sidebar'];\nexport async function importLocalDesignSystemProject(\n  sourceRootInput: string,\n  userDesignSystemsRoot: string,\n  options: LocalDesignSystemImportOptions = {},\n): Promise<LocalDesignSystemImportResult> {\n  const sourceRoot = await realpath(sourceRootInput);\n  const sourceStats = await stat(sourceRoot);\n  if (!sourceStats.isDirectory()) {\n    throw new LocalDesignSystemImportError('BAD_REQUEST', 'local project path must be a directory');\n  }\n\n  const scan = await scanProject(sourceRoot);\n  const displayName = cleanDisplayName(options.name ?? scan.packageName ?? options.fallbackName ?? path.basename(sourceRoot));\n  const id = await reserveNextAvailableSlug(userDesignSystemsRoot, slugify(displayName), options.reservedIds);\n  const outDir = path.join(userDesignSystemsRoot, id);\n  const importMode = normalizeImportMode(options.importMode);\n  const craftApplies = normalizeCraftList(options.craftApplies);\n  const now = options.now ?? new Date();\n\n  const files = [\n    'USAGE.md',\n    'DESIGN.md',\n    'tokens.css',\n    'design-tokens.json',\n    'tailwind-v4.css',\n    'components.html',\n    'components.manifest.json',","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/design-systems/import.ts#L109-L145","documentation":"importLocalDesignSystemProject resolves the source path with realpath and stats it. If the result is not a directory the import cannot proceed, because the scanner walks a folder tree of project files. Files, broken symlinks, and missing paths are rejected as BAD_REQUEST.","triggerScenarios":"Caller passed a path to a single file (a .json or .zip), a broken symlink, or a path that does not exist. realpath/stat resolves the path and isDirectory() returns false.","commonSituations":"Selecting a packaged file instead of the project folder; the folder was moved or deleted after selection; path is a symlink pointing to a file; typo in an absolute path.","solutions":["Select the project's root directory, not a file inside it.","Confirm the path exists and is a folder before importing.","If the path is a symlink, ensure it resolves to a real directory."],"exampleFix":"// before\nawait importLocalDesignSystemProject('/proj/design-system.json', outRoot);\n\n// after\nawait importLocalDesignSystemProject('/proj', outRoot);","handlingStrategy":"validation","validationCode":"import { stat } from 'node:fs/promises';\n\nasync function assertSourceDir(sourceRootInput: string): Promise<void> {\n  const stats = await stat(sourceRootInput);\n  if (!stats.isDirectory()) {\n    throw new Error('local project path must be a directory');\n  }\n}\n\nawait assertSourceDir(sourceRootInput);","typeGuard":"async function isDirectoryPath(p: string): Promise<boolean> {\n  try { return (await stat(p)).isDirectory(); } catch { return false; }\n}","tryCatchPattern":"try {\n  await importLocalDesignSystemProject(sourceRootInput, userRoot);\n} catch (err) {\n  if (isLocalDesignSystemImportError(err) && err.code === 'BAD_REQUEST' && /must be a directory/i.test(err.message)) {\n    // prompt the user to pick the project folder, not a file\n  } else throw err;\n}","preventionTips":["Let the user pick via a directory chooser that disallows file selection.","Stat the path and confirm isDirectory() before invoking the importer.","Resolve symlinks before the check so broken links fail fast."],"tags":["design-systems","local-import","validation"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}