remix-run/react-router · error · CopyTemplateError

There was a problem extracting the file from the provided te

Error message

There was a problem extracting the file from the provided template.  Template filepath: `${tarballPath}`  Destination directory: `${destPath}`  ${error}

What it means

Thrown by extractLocalTarball() when the gunzip/tar-fs stream pipeline rejects while reading a local .tar.gz/.tgz file. The pipeline is fs.createReadStream -> gunzip-maybe -> tar.extract(dest, { strip: 1 }); a failure anywhere (corrupt gzip, truncated file, bad tar header, unreadable path, permissions) is caught and re-wrapped as a CopyTemplateError that includes the tarballPath, destPath, and the underlying error.

Source

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

  throw new CopyTemplateError(
    "The provided template is not a valid local directory or tarball.",
  );
}

const pipeline = promisify(stream.pipeline);

async function extractLocalTarball(
  tarballPath: string,
  destPath: string,
): Promise<void> {
  try {
    await pipeline(
      fs.createReadStream(tarballPath),
      gunzip(),
      tar.extract(destPath, { strip: 1 }),
    );
  } catch (error: unknown) {
    throw new CopyTemplateError(
      "There was a problem extracting the file from the provided template." +
        `  Template filepath: \`${tarballPath}\`` +
        `  Destination directory: \`${destPath}\`` +
        `  ${error}`,
    );
  }
}

interface TarballDownloadOptions {
  debug?: boolean;
  filePath?: string | null;
  token?: string;
}

async function downloadAndExtractRepoTarball(
  repo: RepoInfo,
  destPath: string,
  options: TarballDownloadOptions,

View on GitHub (pinned to 1fd704a7da)

Solutions

  1. Re-download or regenerate the tarball and verify integrity: tar -tzf <file> should list contents without error.
  2. Confirm the file is genuinely gzip+tar and not another format: file <path> (should report 'gzip compressed data').
  3. Check filesystem permissions on both the tarball (read) and the destination (write).
  4. If the archive is .zip, extract it and pass the directory instead, or repackage as tar.gz.
  5. Inspect the appended underlying error string for the exact syscall/errno and address that.

Example fix

// before -- template.tar.gz is corrupt
create-react-router my-app --template ./template.tar.gz
// after -- verify, then repackage
tar -tzf ./template.tar.gz || (rm ./template.tar.gz && curl -L -o ./template.tar.gz <url>)
create-react-router my-app --template ./template.tar.gz
Defensive patterns

Strategy: validation

Validate before calling

import { execSync } from 'node:child_process';
function tarballLooksValid(file: string): boolean {
  try {
    execSync(`tar -tzf "${file}" > /dev/null 2>&1`, { stdio: 'ignore' });
    return true;
  } catch { return false; }
}
// if (!tarballLooksValid(template)) redownload before invoking the CLI

Try / catch

try {
  await copyTemplate(localTarball, dest, { onError: async (e) => { throw e; } });
} catch (e) {
  if (e instanceof CopyTemplateError && /problem extracting/.test(e.message)) {
    // redownload / regenerate tarball, then retry once
  } else throw e;
}

Prevention

When it happens

Trigger: A .tar.gz file that is actually a .zip renamed, a partially-downloaded/truncated tarball, an empty file, gzip data with a corrupt member, a tar entry with paths that cannot be written to destPath, or EBADF/EACCES reading the source or writing the destination.

Common situations: Tarball download was interrupted; file was committed to git with LF/CRLF mangling that corrupts binary data; the file is a different archive format (zip, 7z) with a .tar.gz extension; destPath is on a read-only mount; antivirus locking the file on Windows.

Related errors


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