mastra-ai/mastra · error · Error

Unsupported file extension: ${targzPath}

Error message

Unsupported file extension: ${targzPath}

What it means

decompressToCache() only knows how to extract files with the .gz extension (it pipes them through tar.x). If the downloaded model archive's path has any other extension, it assumes the archive format is unsupported and throws rather than guessing an extractor.

Source

Thrown at packages/fastembed/src/fastembed.ts:320

            reject(error);
          });
        })
        .on('error', error => {
          fs.unlink(outputFilePath, () => {
            reject(error);
          });
        });
    });
  }

  private static async decompressToCache(targzPath: PathLike, cacheDir: PathLike) {
    if (path.extname(targzPath.toString()) === '.gz') {
      await tar.x({
        file: targzPath.toString(),
        cwd: cacheDir.toString(),
      });
    } else {
      throw new Error(`Unsupported file extension: ${targzPath}`);
    }
  }

  static async retrieveModel(
    model: EmbeddingModel,
    cacheDir: PathLike,
    showDownloadProgress: boolean = true,
  ): Promise<PathLike> {
    if (!fs.existsSync(cacheDir)) {
      fs.mkdirSync(cacheDir, { mode: 0o755 });
    }

    const modelDir = path.join(cacheDir.toString(), model);

    if (fs.existsSync(modelDir)) {
      return modelDir;
    }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Check the actual file at the cache path and confirm it is a gzip/tar archive ending in '.gz'; re-download or rename it.
  2. Clear the model cache directory so retrieveModel re-downloads the canonical .tar.gz archive.
  3. If the source is genuinely .tgz or another format, convert it to a .gz tarball, or extend the extraction logic to handle that extension.

Example fix

// before: cache contains model.tgz -> throws
// after: rename/convert to .tar.gz
const { execSync } = require('child_process');
execSync(`gunzip -c model.tgz > model.tar.gz`);
await FastEmbed.retrieveModel(model, cacheDir); // now sees model.tar.gz
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync, statSync } from 'fs';
function isGzipArchive(p) {
  return typeof p === 'string' && existsSync(p) && p.toLowerCase().endsWith('.gz') && statSync(p).size > 0;
}

Type guard

function isPathLikeWithGzExt(p) {
  return typeof p === 'string' && p.toLowerCase().endsWith('.gz');
}

Try / catch

try {
  await FastEmbed.retrieveModel(model, cacheDir);
} catch (e) {
  if (String(e.message).startsWith('Unsupported file extension')) {
    await redownloadModelToCache(model, cacheDir); // replace bad archive with canonical .tar.gz
    return FastEmbed.retrieveModel(model, cacheDir);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling retrieveModel() (which calls decompressToCache) when the cached/downloaded archive path does not end in '.gz', e.g. a .tgz, .zip, or extensionless file in the cache dir.

Common situations: A CDN changed the archive format for a model; the user pre-seeded the cache with a differently-compressed archive; a partial/renamed download left a wrong extension; case mismatch like '.GZ' (path.extname comparison is case-sensitive).

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/44d90ed1e660adc5. Report an issue: GitHub.