{"record":{"id":"7764cdb96b993382","repo":"vercel/turborepo","slug":"iserrorlike-reason-reason-message-string-reas","errorCode":null,"errorMessage":"isErrorLike(reason) ? reason.message : String(reason)","messagePattern":"isErrorLike\\(reason\\) \\? reason\\.message : String\\(reason\\)","errorType":"exception","errorClass":"DownloadError","httpStatus":null,"severity":"error","filePath":"packages/turbo-utils/src/create-project.ts","lineNumber":214,"sourceCode":"      } catch {\n        // ignore\n      }\n\n      if (packageJsonContent) {\n        // read the scripts from the package.json\n        availableScripts.push(...Object.keys(packageJsonContent.scripts || {}));\n      }\n    }\n\n    let cdPath: string = appPath;\n    if (path.join(originalDirectory, appName) === appPath) {\n      cdPath = appName;\n    }\n\n    return { cdPath, hasPackageJson, availableScripts, repoInfo };\n  } catch (reason) {\n    loader.stop();\n    throw new DownloadError(\n      isErrorLike(reason) ? reason.message : String(reason)\n    );\n  }\n}\n","sourceCodeStart":196,"sourceCodeEnd":219,"githubUrl":"https://github.com/vercel/turborepo/blob/f9245100cf0d31d96628804ead485f6bf226e55a/packages/turbo-utils/src/create-project.ts#L196-L219","documentation":"createProject wraps its entire download/extract/inspect phase and rethrows any failure as a DownloadError, carrying the original message (reason.message when error-like, String(reason) otherwise). So this error is a facade: the text you see comes from whatever failed underneath - a fetch error, a GitHub API response, a tar extraction error, or a package.json parse failure.","triggerScenarios":"Any exception inside createProject: the repo metadata fetch (GitHub API), the tarball download (see 'Failed to download: <status>'), missing network (ENOTFOUND/ECONNREFUSED), invalid example name, or errors while reading scripts from the extracted package.json. The loader is stopped and the original message is wrapped.","commonSituations":"Offline or proxied networks during create-turbo, GitHub API rate limits (secondary rate limit JSON responses), DNS failures in CI, or a template whose package.json cannot be read/parsed after extraction.","solutions":["Read the inner message - it is the real cause; treat this error as a wrapper, not a diagnosis","If the inner text mentions a status code (403/429), handle GitHub rate limiting: wait or authenticate","If it is a socket/DNS error, fix network/proxy env (HTTPS_PROXY) and retry","If it is a parse error, the downloaded template is corrupt; retry or pick another example","Retry transiently: this path has no built-in retry, one attempt then throw"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Cheap connectivity pre-flight before createProject\nimport { lookup } from \"node:dns/promises\";\nasync function networkUp(host = \"codeload.github.com\"): Promise<boolean> {\n  try { await lookup(host); return true; } catch { return false; }\n}","typeGuard":"import { DownloadError } from \"@turbo-utils\";\n\nfunction isDownloadError(err: unknown): err is DownloadError {\n  return err instanceof DownloadError;\n}","tryCatchPattern":"try {\n  const { appPath } = await createProject(opts);\n} catch (err) {\n  if (err instanceof DownloadError) {\n    console.error(\"Template download failed:\", err.message); // inner cause is the real diagnosis\n    if (/ENOTFOUND|ECONNREFUSED|fetch failed/.test(err.message)) {\n      // network issue - guide user to check proxy/offline state\n    }\n  }\n  throw err;\n}","preventionTips":["Check network/proxy before running create-turbo in automation","Wrap createProject and surface err.message - it wraps the true cause","Keep an offline fallback: a local template directory instead of a remote one"],"tags":["network","download","create-turbo","error-wrapping"],"backgroundTag":"download-failed","analyzedSha":"f9245100cf0d31d96628804ead485f6bf226e55a","analyzedAt":"2026-08-17T10:46:15.696Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}