{"record":{"id":"6b15813059647690","repo":"mastra-ai/mastra","slug":"failed-to-clone-repository-giterror-instanceof","errorCode":null,"errorMessage":"Failed to clone repository: ${gitError instanceof Error ? gitError.message : 'Unknown error'}","messagePattern":"Failed to clone repository: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"mastracode/mastra-factory/src/utils/clone.ts","lineNumber":73,"sourceCode":"\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        );\n      }\n    }\n\n    if (await pathExists(targetPath)) {\n      throw new Error(`Directory ${path.basename(targetPath)} already exists`);\n    }\n    await fs.rename(tempTarget, targetPath);\n  } finally {\n    await fs.rm(tempRoot, { recursive: true, force: true });\n  }\n}\n","sourceCodeStart":55,"sourceCodeEnd":87,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/mastra-factory/src/utils/clone.ts#L55-L87","documentation":"When degit fails (including the empty-directory case), cloneTemplate falls back to `git clone <repoUrl> <tempTarget>`. If that git clone also throws, the error is rethrown wrapped as 'Failed to clone repository: <git message>' with the temp dir cleaned up. It is the terminal error meaning both scaffold strategies failed.","triggerScenarios":"The degit path threw (caught by the outer catch), and the fallback `git clone repoUrl tempTarget` also failed — non-zero git exit, missing git binary, unreachable remote, bad URL, or cleanup of tempTarget itself throwing.","commonSituations":"Private repos without credentials, wrong repoUrl after a repo was renamed/deleted, no network or blocked git://(https) access, git not on PATH, or SSH keys absent when the URL is SSH-based.","solutions":["Read the wrapped git message for the root cause (auth prompt, 404, DNS) and fix accordingly","Verify the repo URL exists and is accessible: `git ls-remote <repoUrl>`","For private repos, configure credentials (SSH key, token in the URL, or git credential helper)","Ensure git is installed and on PATH (`git --version`)","Check network/proxy settings if the remote is unreachable"],"exampleFix":"// before\nawait x('git', ['clone', 'https://github.com/acme/private-template.git', tempTarget], { throwOnError: true });\n// after\nawait x('git', ['clone', 'https://<TOKEN>@github.com/acme/private-template.git', tempTarget], { throwOnError: true });","handlingStrategy":"try-catch","validationCode":"const { code } = await x('git', ['ls-remote', repoUrl], { throwOnError: false });\nif (code !== 0) throw new Error(`repo unreachable: ${repoUrl}`);","typeGuard":"null","tryCatchPattern":"try {\n  await cloneTemplate(opts);\n} catch (err) {\n  const msg = (err as Error).message;\n  if (msg.startsWith('Failed to clone repository')) {\n    console.error('Both degit and git clone failed:', msg);\n    // surface auth/network remediation to the user\n  } else throw err;\n}","preventionTips":["Run `git ls-remote <url>` in CI before scaffolding","Configure credentials (SSH keys or token URLs) for private templates","Ensure git is installed in the runtime image"],"tags":["git","network","fallback-failure"],"backgroundTag":"git-clone-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}