{"record":{"id":"e9082b14651d4b63","repo":"mastra-ai/mastra","slug":"degit-completed-without-cloning-template-files","errorCode":null,"errorMessage":"degit completed without cloning template files","messagePattern":"degit completed without cloning template files","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/mastra-factory/src/utils/clone.ts","lineNumber":57,"sourceCode":"\nexport async function cloneTemplate(repoUrl: string, targetPath: string): Promise<void> {\n  if (await pathExists(targetPath)) {\n    throw new Error(`Directory ${path.basename(targetPath)} already exists`);\n  }\n\n  const tempRoot = await fs.mkdtemp(path.join(path.dirname(targetPath), `.${path.basename(targetPath)}-`));\n  const tempTarget = path.join(tempRoot, 'template');\n\n  try {\n    try {\n      const degitRepo = repoUrl.replace('https://github.com/', '');\n      await x('npx', ['degit', degitRepo, tempTarget], {\n        throwOnError: true,\n        nodeOptions: { cwd: process.cwd() },\n      });\n\n      if ((await fs.readdir(tempTarget)).length === 0) {\n        throw new Error('degit completed without cloning template files');\n      }\n    } catch {\n      await fs.rm(tempTarget, { recursive: true, force: true });\n\n      try {\n        await x('git', ['clone', repoUrl, tempTarget], {\n          throwOnError: true,\n          nodeOptions: { cwd: process.cwd() },\n        });\n\n        const gitDir = path.join(tempTarget, '.git');\n        if (await directoryExists(gitDir)) {\n          await fs.rm(gitDir, { recursive: true, force: true });\n        }\n      } catch (gitError) {\n        throw new Error(\n          `Failed to clone repository: ${gitError instanceof Error ? gitError.message : 'Unknown error'}`,\n        );","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/mastra-factory/src/utils/clone.ts#L39-L75","documentation":"cloneTemplate first attempts to scaffold a template via `npx degit <repo> <target>`. degit can exit 0 while producing an empty directory (e.g. an invalid or renamed repo spec, network middleware issues, or degit's cache behaving badly), so the code treats an empty tempTarget as a failed clone and throws to fall back to `git clone`.","triggerScenarios":"`cloneTemplate` runs `npx degit <repo> <target>` with throwOnError, then `fs.readdir(tempTarget)` returns 0 entries — degit exited successfully but wrote nothing (bad/renamed user/repo#ref spec, degit tarball fetch producing an empty extraction).","commonSituations":"Typo in the degit shorthand (e.g. 'user/nonexistent-repo' or wrong branch after a repo renamed its default branch), offline/proxy environments where degit silently no-ops, stale degit cache for a deleted ref, or a template repo that is genuinely empty.","solutions":["Verify the degit repo spec (`owner/repo[#ref]`) points to a non-empty repo/ref, then retry","Re-run with the network available (degit downloads a tarball; offline runs produce nothing)","Clear degit's cache (~/.degit) if a stale cached entry is suspected","Let the built-in fallback run: this throw triggers the git clone fallback path, so check that git is installed and the repo URL is reachable","Clone the template manually with git to confirm it has content"],"exampleFix":"// before\nawait x('npx', ['degit', 'acme/renamed-template', tempTarget], { throwOnError: true });\n// after\nawait x('npx', ['degit', 'acme/correct-template-name', tempTarget], { throwOnError: true });","handlingStrategy":"fallback","validationCode":"const entries = await fs.readdir(templateDir);\nif (entries.length === 0) throw new Error(`template ${repo} has no files`);","typeGuard":"null","tryCatchPattern":"try {\n  await cloneTemplate(opts);\n} catch (err) {\n  if ((err as Error).message.includes('degit completed without cloning')) {\n    // fall back to manual git clone\n    await x('git', ['clone', repoUrl, target], { throwOnError: true });\n  } else throw err;\n}","preventionTips":["Verify the degit spec with `npx degit --dry-run` style checks or `git ls-remote`","Confirm the template repo/ref is non-empty before scaffolding","Keep the git-clone fallback path available (git installed)"],"tags":["filesystem","network","template-scaffold"],"backgroundTag":"empty-clone-result","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}