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. Perhaps your `--token`is expired or invalid.

What it means

Thrown when the final fetch of the resolved resourceUrl (release asset API URL or the original tarball URL) returns a non-200 status or no body, AND a --token was supplied. Because a token is present, the message specifically suggests the token is expired or invalid rather than a generic transient failure. isGithubUrl (host ends with github.com) controls whether 'from GitHub' is inserted.

Source

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

      // If the release is "latest", the url won't match the download url
      return info.tag === "latest"
        ? asset?.browser_download_url?.includes(info.asset)
        : asset?.browser_download_url === tarballUrl;
    })?.id;
    if (assetId == null) {
      throw new CopyTemplateError(
        "There was a problem fetching the file from GitHub. No asset was " +
          "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);

View on GitHub (pinned to 1fd704a7da)

Solutions

  1. Generate a fresh token (classic PAT with 'repo' or a fine-grained PAT with 'Contents: read' on the repo) and pass --token again.
  2. Confirm the token works against the API: curl -H 'Authorization: token <TOKEN>' https://api.github.com/...
  3. Verify the token has not been revoked and the owning account still has access to the repo/release.
  4. If you intentionally have no auth needs, drop --token to get the no-token variant of the message and debug as anonymous.

Example fix

// before
create-react-router my-app --token ghp_OLDTOKEN --template https://github.com/acme/private/releases/download/v1/app.tar.gz
// after -- fresh token with Contents: read
create-react-router my-app --token $(cat ~/.config/crr-token) --template https://github.com/acme/private/releases/download/v1/app.tar.gz
Defensive patterns

Strategy: validation

Validate before calling

// Confirm a token is live and has access before scaffolding
async function tokenCanReadRepo(token: string, owner: string, repo: string) {
  const r = await fetch(`https://api.github.com/repos/${owner}/${repo}`, {
    headers: { Authorization: `token ${token}`, Accept: 'application/vnd.github.v3+json' },
  });
  return r.status === 200;
}

Try / catch

try { await copyTemplate(url, dest, { ...opts, token }); }
catch (e) {
  if (e instanceof CopyTemplateError && /--token/.test(e.message)) {
    // rotate token, verify scopes, then retry once
  } else throw e;
}

Prevention

When it happens

Trigger: The supplied --token is expired, revoked, or lacks scope for the asset; asset requires a paid/private scope; token has read:packages but not repo access; rate limit per-token exceeded (403); the asset URL was valid but was just deleted (404).

Common situations: Long-lived CI token rotated by an org policy; fine-grained PAT without the 'Contents: read' permission; token belongs to an account that lost access to the repo; copy-paste error introduced whitespace into the token.

Related errors


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