ruvnet/ruflo · error · ExtractionError

archive did not contain the expected binary at its root: ${b

Error message

archive did not contain the expected binary at its root: ${binaryNameInArchive()}

What it means

Error "archive did not contain the expected binary at its root: ${binaryNameInArchive()}" thrown in ruvnet/ruflo.

Source

Thrown at v3/@claude-flow/cli/src/proxy/install.ts:153

      assetBytes: assets.archiveBytes,
      assetFilename: assets.archiveFilename,
    });
    log(`Verified — sha256 ${sha256.slice(0, 16)}…`);

    // fetchReleaseAssets's dev (gh) path already wrote the archive to workDir
    // under archiveFilename; ensure it's there regardless of source so
    // extraction always has a real file to operate on.
    const archivePath = path.join(workDir, archiveFilename);
    if (!fs.existsSync(archivePath)) {
      fs.writeFileSync(archivePath, assets.archiveBytes);
    }

    const extractDir = path.join(workDir, 'extracted');
    await extractArchive(archivePath, extractDir, releaseArchiveExtension(triple));

    const extractedBinaryPath = path.join(extractDir, binaryNameInArchive());
    if (!fs.existsSync(extractedBinaryPath)) {
      throw new ExtractionError(`archive did not contain the expected binary at its root: ${binaryNameInArchive()}`);
    }

    // Defense in depth: confirm the extracted binary genuinely resolves
    // inside extractDir (catches a symlink swap or similar), even though
    // we only ever read one specific expected relative path, never an
    // archive-listed one (so "zip slip" via arbitrary archive paths isn't
    // reachable here in the first place).
    const { PathValidator } = await import('@claude-flow/security');
    const validator = new PathValidator({ allowedPrefixes: [extractDir] });
    const validation = await validator.validate(extractedBinaryPath);
    if (!validation.isValid) {
      throw new ExtractionError(`extracted binary path failed validation: ${validation.errors.join('; ') || 'unknown'}`);
    }

    const finalPath = proxyBinaryPath();
    fs.mkdirSync(path.dirname(finalPath), { recursive: true, mode: 0o700 });
    const tmp = `${finalPath}.tmp`;
    fs.copyFileSync(extractedBinaryPath, tmp);

View on GitHub (pinned to 6b01dc5a68)

When it happens

Trigger: Thrown at v3/@claude-flow/cli/src/proxy/install.ts:153 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12). Data as JSON: /api/errors/add42de5e916f1fe. Report an issue: GitHub.