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
- Open the release URL in a browser to confirm the repo, tag, and asset exist
- If using --token, verify it is valid and has access to the repo
- Check rate limits: curl https://api.github.com/rate_limit — wait and retry when exhausted
- 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
- Always export GITHUB_TOKEN / pass --token in CI to raise the API quota from 60/h to 5000/h
- Pin exact release tags instead of 'latest' in cached scripts
- Check api.github.com/rate_limit before large scaffold batches
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
- There was a problem fetching the file
- There was a problem fetching the file from GitHub. No asset…
- There was a problem fetching the file
- No available port found
- No response body
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)