remix-run/react-router · error · CopyTemplateError

There was a problem fetching the file${isGithubUrl ? " from

Error message

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

What it means

Thrown for the same failed final fetch (resourceUrl returned non-200 or empty body) when NO --token was supplied. The message is the generic 'Please try again later' variant, since without auth the assumption is a transient server error, rate limiting, or a missing/public-but-removed resource rather than a credential issue.

Source

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

          "found at that url. Please try again later.",
      );
    }
    resourceUrl = `https://api.github.com/repos/${info.owner}/${info.name}/releases/assets/${assetId}`;
    headers.Accept = "application/octet-stream";
  }
  let response = await fetch(resourceUrl, { headers });

  if (!response.body || response.status !== 200) {
    if (token) {
      throw new CopyTemplateError(
        `There was a problem fetching the file${
          isGithubUrl ? " from GitHub" : ""
        }. The request ` +
          `responded with a ${response.status} status. Perhaps your \`--token\`` +
          "is expired or invalid.",
      );
    }
    throw new CopyTemplateError(
      `There was a problem fetching the file${
        isGithubUrl ? " from GitHub" : ""
      }. The request ` +
        `responded with a ${response.status} status. Please try again later.`,
    );
  }

  // file paths returned from GitHub are always unix style
  if (filePath) {
    filePath = filePath.split(path.sep).join(path.posix.sep);
  }

  let filePathHasFiles = false;

  try {
    let input = new stream.PassThrough();
    // Start reading stream into passthrough, don't await to avoid buffering
    writeReadableStreamToWritable(response.body, input);

View on GitHub (pinned to 1fd704a7da)

Solutions

  1. Retry after a short wait; if you suspect rate limiting, check X-RateLimit-Remaining on api.github.com.
  2. For repeated/CI usage, supply --token to move from the 60/hr anonymous limit to the 5000/hr authenticated limit.
  3. Confirm the URL still resolves (curl -I <url>) and that the host is up.
  4. If using a non-GitHub tarball host, ensure it permits anonymous GET and serves a 200.

Example fix

// before -- anonymous, rate-limited
create-react-router my-app --template https://github.com/acme/tpl/releases/download/v1/app.tar.gz
// after -- add a token for CI
create-react-router my-app --token $GITHUB_TOKEN --template https://github.com/acme/tpl/releases/download/v1/app.tar.gz
Defensive patterns

Strategy: retry

Validate before calling

// Check rate-limit budget before an anonymous run
async function anonymousBudgetAvailable() {
  const r = await fetch('https://api.github.com/rate_limit');
  const b = await r.json();
  return (b.resources.core.remaining > 0);
}

Try / catch

for (let attempt = 0; attempt < 3; attempt++) {
  try { await copyTemplate(url, dest, opts); break; }
  catch (e) {
    if (e instanceof CopyTemplateError && /Please try again later/.test(e.message)) {
      await delay(1000 * 2 ** attempt); continue;
    }
    throw e;
  }
}

Prevention

When it happens

Trigger: Anonymous GitHub rate limit exceeded (403); transient GitHub 5xx; asset or release removed (404); network blip returning a non-200; non-GitHub tarball host returning 403/404/500.

Common situations: CI without a token doing many create-react-router runs per hour; the tarball host is temporarily down; a CDN edge serving a stale 404; release was just published and not yet propagated to the API.

Related errors


AI-assisted analysis of remix-run/react-router@1fd704a7da (2026-08-12). Data as JSON: /api/errors/55c4f6135230ca23. Report an issue: GitHub.