remix-run/react-router · error · CopyTemplateError

There was a problem fetching the file from GitHub. The…

Error message

There was a problem fetching the file from GitHub. The request responded with a ${response.status} status. Please try again later.

What it means

When the template URL is a GitHub release asset URL (containing /releases/download/ or /releases/latest/download/), the CLI first queries api.github.com for the release metadata to look up the asset id. This error means that API call returned a non-200 status: 404 (repo or tag does not exist), 401 (bad credentials), or 403 (rate limit exceeded).

Solutions

  1. Open the release URL in a browser to confirm the repo, tag, and asset exist
  2. If using --token, verify it is valid and has access to the repo
  3. Check rate limits: curl https://api.github.com/rate_limit — wait and retry when exhausted
  4. Prefer the exact form /releases/download/<tag>/<asset>.tar.gz over /releases/latest/download/

Example fix

# before (tag typo)
npx create-react-router my-app --token $GH_TOKEN \
  --template https://github.com/acme/templates/releases/download/v1.0/template.tar.gz

# after: confirm the tag exists, then use the exact asset URL
curl -s https://api.github.com/repos/acme/templates/releases | grep tag_name
npx create-react-router my-app --token $GH_TOKEN \
  --template https://github.com/acme/templates/releases/download/v1.0.0/template.tar.gz
Defensive patterns

Strategy: retry

Validate before calling

async function preflightRelease(owner: string, repo: string, tag: string, token?: string) {
  const headers: Record<string, string> = { Accept: "application/vnd.github.v3+json" };
  if (token) headers.Authorization = `token ${token}`;
  const res = await fetch(
    `https://api.github.com/repos/${owner}/${repo}/releases/tags/${tag}`,
    { headers },
  );
  if (res.status === 404) throw new Error(`Release ${tag} not found in ${owner}/${repo}`);
  if (res.status === 401) throw new Error("Token invalid");
  if (res.status === 403) throw new Error("Rate limited — set GITHUB_TOKEN or wait");
  if (!res.ok) throw new Error(`GitHub API ${res.status}`);
  return res.json();
}

Try / catch

async function scaffoldWithRetry(args: string[], attempts = 3) {
  for (let i = 0; i < attempts; i++) {
    try {
      return await createReactRouter(args);
    } catch (e) {
      const msg = e instanceof Error ? e.message : String(e);
      const transient = /problem fetching the file from GitHub/.test(msg) && !/404|401/.test(msg);
      if (!transient || i === attempts - 1) throw e;
      await new Promise((r) => setTimeout(r, 2 ** i * 5_000));
    }
  }
}

Prevention

When it happens

Trigger: Template URL references a deleted repo, a nonexistent or draft tag, or a repo with no releases when using /releases/latest/; a revoked --token; unauthenticated GitHub API rate limiting (60 requests/hour per IP) in CI.

Common situations: Shared CI runners behind one NAT exhausting the unauthenticated quota; typos in tag names; draft releases not visible to the API without auth; rotated tokens.

Related errors


AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18). Data as JSON: /api/errors/08df4818d07d6ad9. Report an issue: GitHub.

Appendix: source

Thrown at packages/create-react-router/copy-template.ts:231

  let isGithubUrl = new URL(tarballUrl).host.endsWith("github.com");
  if (token && isGithubUrl) {
    headers.Authorization = `token ${token}`;
  }
  if (isGithubReleaseAssetUrl(tarballUrl)) {
    // We can download the asset via the GitHub api, but first we need to look
    // up the asset id
    let info = getGithubReleaseAssetInfo(tarballUrl);
    headers.Accept = "application/vnd.github.v3+json";

    let releaseUrl =
      info.tag === "latest"
        ? `https://api.github.com/repos/${info.owner}/${info.name}/releases/latest`
        : `https://api.github.com/repos/${info.owner}/${info.name}/releases/tags/${info.tag}`;

    let response = await fetch(releaseUrl, { headers });

    if (response.status !== 200) {
      throw new CopyTemplateError(
        "There was a problem fetching the file from GitHub. The request " +
          `responded with a ${response.status} status. Please try again later.`,
      );
    }

    let body = (await response.json()) as { assets: GitHubApiReleaseAsset[] };
    if (
      !body ||
      typeof body !== "object" ||
      !body.assets ||
      !Array.isArray(body.assets)
    ) {
      throw new CopyTemplateError(
        "There was a problem fetching the file from GitHub. No asset was " +
          "found at that url. Please try again later.",
      );
    }

View on GitHub (pinned to 6beaca3952)