{"record":{"id":"c7a85eea85a375ff","repo":"vercel/turborepo","slug":"git-download-failed-formaterror-giterror-fall","errorCode":null,"errorMessage":"Git download failed:\n${formatError(gitError)}\nFalling back to downloading the example via tarball.","messagePattern":"Git download failed:\n(.+?)\nFalling back to downloading the example via tarball\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/turbo-utils/src/examples.ts","lineNumber":573,"sourceCode":"      \"--no-checkout\",\n      \"--depth\",\n      \"1\",\n      \"--sparse\",\n      \"https://github.com/vercel/turborepo.git\",\n      tempDir\n    ]);\n\n    // Set up sparse checkout for just the example we want\n    runGit([\"sparse-checkout\", \"set\", `examples/${name}`], tempDir);\n\n    // Checkout the files\n    runGit([\"checkout\"], tempDir);\n\n    // Copy the example files to the root\n    const examplePath = join(tempDir, \"examples\", name);\n    cpSync(examplePath, normalizedRoot, { recursive: true });\n  } catch (gitError) {\n    warn(\n      `Git download failed:\\n${formatError(gitError)}\\n` +\n        \"Falling back to downloading the example via tarball.\"\n    );\n    cleanupCloneDirectory(tempDir);\n\n    await streamingExtract({\n      url: \"https://codeload.github.com/vercel/turborepo/tar.gz/main\",\n      root: normalizedRoot,\n      strip: 3,\n      filter: (p: string, rootPath: string | null) => {\n        return p.startsWith(`${rootPath}/examples/${name}/`);\n      }\n    });\n\n    return;\n  }\n\n  // Clean up the temp directory on success","sourceCodeStart":555,"sourceCodeEnd":591,"githubUrl":"https://github.com/vercel/turborepo/blob/f9245100cf0d31d96628804ead485f6bf226e55a/packages/turbo-utils/src/examples.ts#L555-L591","documentation":"downloadAndExtractExample() first tries the fast path: a blobless, sparse, shallow `git clone` of vercel/turborepo followed by `sparse-checkout set examples/<name>` and `checkout`. Any failure in that chain (runGit wraps execFileSync and throws `\\`git <subcommand>\\` failed`) is caught here, warned about, and the code falls back to streaming the codeload.github.com tarball. The message is informational: it names the git error and states the fallback; only if the tarball download also fails does the operation actually throw.","triggerScenarios":"execFileSync('git', ...) fails for any of: git not installed (ENOENT), git older than 2.25 (no `sparse-checkout set`; partial clone `--filter=blob:none` needs >= 2.19), network egress to github.com blocked by a corporate firewall/proxy (git does not honor https_proxy the way undici does here), TLS/credential helper misconfiguration, or a leftover conflict-marked .turbo-clone-temp directory making cpSync fail — e.g. running `create-turbo --example <name>` on a minimal Docker image or locked-down CI runner.","commonSituations":"`node:<slim>`/alpine Docker images without the git package; CI runners behind an egress proxy that allows HTTPS fetch (so the tarball fallback works) but blocks git's smart HTTP or DNS; ancient git from a distro repo; flaky networks where the clone times out. Users usually see this warning and the scaffold still succeeds via the tarball.","solutions":["Treat it as benign if the tarball fallback completes — the example is fetched either way; verify the generated files exist.","Install or upgrade git: `apt-get update && apt-get install -y git` (Debian/alpine: `apk add git`), or on macOS `brew install git`; ensure git >= 2.25 for `sparse-checkout set`.","If behind a proxy, configure git explicitly: `git config --global http.proxy $HTTPS_PROXY` (git ignores undici's ProxyAgent path), or allow egress to github.com and objects.githubusercontent.com.","Remove a stale `.turbo-clone-temp` directory in the target root if a previous run was killed mid-clone, then re-run create-turbo.","If both paths fail, debug the tarball URL directly: `curl -fL https://codeload.github.com/vercel/turborepo/tar.gz/main -o /dev/null` to confirm egress."],"exampleFix":"# before: minimal image, git missing -> 'Git download failed' warning\nFROM node:22-slim\nRUN npx create-turbo@latest\n\n# after: git present, fast path succeeds\nFROM node:22-slim\nRUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*\nRUN npx create-turbo@latest","handlingStrategy":"validation","validationCode":"import { execFileSync } from \"node:child_process\";\nfunction gitFastPathAvailable(): boolean {\n  try {\n    const out = execFileSync(\"git\", [\"--version\"], { stdio: [\"pipe\", \"pipe\", \"pipe\"] }).toString();\n    const m = out.match(/(\\d+)\\.(\\d+)/); // needs >= 2.25 for `sparse-checkout set`\n    return !!m && (+m[1] > 2 || (+m[1] === 2 && +m[2] >= 25));\n  } catch {\n    return false; // git missing -> expect the warning, tarball fallback will be used\n  }\n}","typeGuard":null,"tryCatchPattern":"// downloadAndExtractExample already catches internally and falls back to the tarball;\n// only the fallback itself can throw, so wrap the call and retry on network errors:\ntry {\n  await downloadAndExtractExample(root, exampleName);\n} catch (err) {\n  if (err instanceof Error && /ENOTFOUND|ETIMEDOUT|ECONNRESET|fetch failed/.test(err.message)) {\n    await downloadAndExtractExample(root, exampleName); // one retry for transient egress failure\n  } else {\n    throw err;\n  }\n}","preventionTips":["Install git (>= 2.25) in Docker/CI images where you run create-turbo to keep the fast path available.","When behind a corporate proxy, set git's own config (git config --global http.proxy ...) — the library's undici ProxyAgent does not apply to the git subprocess.","Clean up .turbo-clone-temp in the target directory if a previous scaffold was interrupted.","Read the warning as 'degraded, not failed': confirm the example files landed before investigating the git error."],"tags":["git","network","fallback","create-turbo","proxy","ci"],"backgroundTag":"git-clone-failure","analyzedSha":"f9245100cf0d31d96628804ead485f6bf226e55a","analyzedAt":"2026-08-17T10:46:15.696Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}