{"record":{"id":"af17e82404e549f7","repo":"nextlevelbuilder/ui-ux-pro-max-skill","slug":"source-directory-does-not-exist-sourcedir","errorCode":null,"errorMessage":"Source directory does not exist: ${sourceDir}","messagePattern":"Source directory does not exist: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/scripts/sync-assets.mjs","lineNumber":126,"sourceCode":"  for (const file of allFiles) {\n    const sourcePath = join(sourceDir, file);\n    const targetPath = join(targetDir, file);\n\n    if (!sourceFiles.includes(file)) {\n      drift.push(`extra asset file: ${label}/${file}`);\n    } else if (!targetFiles.includes(file)) {\n      drift.push(`missing asset file: ${label}/${file}`);\n    } else if ((await fileHash(sourcePath)) !== (await fileHash(targetPath))) {\n      drift.push(`stale asset file: ${label}/${file}`);\n    }\n  }\n}\n\n// Mirrors sourceDir -> targetDir (deletes targetDir first, so removed\n// source files don't linger as orphans in the target).\nasync function syncDir(sourceDir, targetDir) {\n  if (!(await exists(sourceDir))) {\n    throw new Error(`Source directory does not exist: ${sourceDir}`);\n  }\n\n  const resolvedTarget = assertInsideRepo(targetDir);\n  if (await exists(resolvedTarget)) {\n    await rm(resolvedTarget, { recursive: true, force: true });\n  }\n\n  for (const file of await listFiles(sourceDir)) {\n    if (isExcludedAssetFile(file)) continue;\n    const targetPath = assertInsideRepo(join(resolvedTarget, file));\n    await mkdir(dirname(targetPath), { recursive: true });\n    await writeFile(targetPath, toLF(await readFile(join(sourceDir, file), 'utf8')));\n  }\n}\n\nasync function checkAssets() {\n  const drift = [];\n","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/nextlevelbuilder/ui-ux-pro-max-skill/blob/a38d04c3d5c298c851dbe5e6ee1965ee3de42cb5/cli/scripts/sync-assets.mjs#L108-L144","documentation":"syncDir() refuses to mirror when the source directory doesn't exist. Sources are src/ui-ux-pro-max/{data,scripts,templates} and .claude/skills/<sub-skill> folders. This almost always means the checkout is incomplete — a sparse/partial clone, a shallow CI checkout missing paths, or the script being run outside the standard repo layout.","triggerScenarios":"Running `npm run sync:assets` when src/ui-ux-pro-max/ was never checked out (sparse clone, misconfiguration, or the folder renamed); adding a name to the subSkills array whose .claude/skills/<name> directory doesn't exist yet; running the script from a copied cli/ folder without the rest of the repo.","commonSituations":"Sparse CI checkouts that only fetch cli/; renames of src/ui-ux-pro-max not propagated to sync-assets.mjs; a new sub-skill listed in the array before its directory is committed.","solutions":["Verify the source dir exists: `ls src/ui-ux-pro-max/{data,scripts,templates}` from the repo root.","If missing, fix the checkout (full clone, un-sparse the paths) — do not create empty dirs to silence the error.","If a path was renamed, update sourceRoot/dirsToSync/subSkills in cli/scripts/sync-assets.mjs to the new names.","Ensure new sub-skills have their .claude/skills/<name> directory committed before adding them to the array."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// preflight: every source dir the script will sync must exist\nimport { stat } from 'node:fs/promises';\n\nasync function assertDir(p: string, label: string) {\n  try { await stat(p); } catch {\n    throw new Error(`Missing source directory ${label} (${p}) - incomplete checkout?`);\n  }\n}\n\nfor (const dir of ['data', 'scripts', 'templates']) {\n  await assertDir(join('src', 'ui-ux-pro-max', dir), `src/ui-ux-pro-max/${dir}`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["CI should run check:assets/sync:assets only on full (non-sparse) checkouts.","Commit new sub-skill directories in the same change that adds them to the subSkills array.","If the src layout is renamed, update sync-assets.mjs constants in the same commit."],"tags":["build","sync","filesystem","developer-tooling"],"backgroundTag":null,"analyzedSha":"a38d04c3d5c298c851dbe5e6ee1965ee3de42cb5","analyzedAt":"2026-08-14T18:51:02.321Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}