remix-run/react-router · error · CopyTemplateError
There was a problem extracting the file from the provided…
Error message
There was a problem extracting the file from the provided template. Template URL: `${tarballUrl}` Destination directory: `${downloadPath}` What it means
After a successful HTTP 200 download, the gzip/tar extraction pipeline threw while streaming the response body into the destination. The body was not a valid gzipped tarball: an HTML error page served under a 200 (SPA catch-all hosting), a tarball compressed with something other than gzip (zstd/xz), or a stream interrupted mid-transfer.
Solutions
- Verify the URL serves real gzip data: curl -sL <url> | file - should report 'gzip compressed data'
- Re-pack the archive as gzip-compressed tar and re-host it
- If behind a proxy, bypass it or configure it correctly, then retry
- Re-run with --debug to see which stream stage failed
Example fix
# before: SPA host serves index.html for the tarball path npx create-react-router my-app --template https://tpl.example.com/template.tar.gz # after: confirm and fix hosting so the URL serves gzip curl -sL https://tpl.example.com/template.tar.gz | file - # -> 'gzip compressed data' (not HTML document)
Defensive patterns
Strategy: try-catch
Validate before calling
async function urlServesGzipTarball(url: string): Promise<boolean> {
const res = await fetch(url);
if (!res.ok) return false;
const buf = Buffer.from(await res.arrayBuffer());
// gzip magic number 0x1f 0x8b
return buf.length > 2 && buf[0] === 0x1f && buf[1] === 0x8b;
}
if (!(await urlServesGzipTarball(templateUrl))) {
throw new Error("Template URL does not serve gzip data (check hosting/catch-all routes)");
} Try / catch
try {
await copyTemplate(templateUrl, dest, { onError: (e) => { throw e; } });
} catch (e) {
if (e instanceof CopyTemplateError && /problem extracting the file from the provided template/.test(e.message)
&& /Template URL:/.test(e.message)) {
console.error("Downloaded body was not a valid gzipped tarball — verify the URL with curl.");
process.exit(1);
}
throw e;
} Prevention
- Smoke-test template URLs with curl -sL <url> | file - before wiring them into scripts
- Disable SPA catch-all rewrites for .tar.gz paths on static hosts
- Create archives with gzip compression only (tar -czf), not zstd or xz
When it happens
Trigger: A template URL on a static host with a catch-all route returning index.html for unknown paths; proxy/MITM mangling the body; network reset during streaming; archives packed with non-gzip compression renamed to .tar.gz.
Common situations: Self-hosted template tarballs behind SPA rewrites; corporate proxies corrupting binary transfers; flaky CI networks truncating downloads.
Related errors
- There was a problem extracting the file from the provided…
- No available port found
- There was a problem fetching the file
- " " is an invalid template. Run to see supported template…
- Exiting to avoid overwriting files
AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18).
Data as JSON: /api/errors/f417b57905779436.
Report an issue: GitHub.
Appendix: source
Thrown at packages/create-react-router/copy-template.ts:332
filePathHasFiles = true;
header.name = header.name.replace(filePath, "");
} else {
header.name = "__IGNORE__";
}
}
return header;
},
ignore(_filename, header) {
if (!header) {
throw Error("Header is undefined");
}
return header.name === "__IGNORE__";
},
}),
);
} catch {
throw new CopyTemplateError(
"There was a problem extracting the file from the provided template." +
` Template URL: \`${tarballUrl}\`` +
` Destination directory: \`${downloadPath}\``,
);
}
if (filePath && !filePathHasFiles) {
throw new CopyTemplateError(
`The path "${filePath}" was not found in this ${
isGithubUrl ? "GitHub repo." : "tarball."
}`,
);
}
}
// Copied from react-router-node/stream.ts
async function writeReadableStreamToWritable(
stream: ReadableStream,View on GitHub (pinned to 6beaca3952)