ruvnet/ruflo · error

gh release download failed

Error message

gh release download failed (exit ${result.exitCode}): ${result.stderr || result.stdout}

What it means

The dev/internal download path (enabled via RUFLO_DEV_PROXY_INSTALL / release-source override) shells out to `gh release download -R cognitum-one/meta-proxy` through SafeExecutor; a non-zero exit code is surfaced verbatim with gh's stderr or stdout. The embedded text is gh's own output, which distinguishes auth, not-found, and network causes.

Solutions

  1. Read the embedded gh stderr — it names the exact cause (auth vs not-found vs network)
  2. Install gh and authenticate: `gh auth login`, verify with `gh auth status`
  3. Test access directly: `gh release view -R cognitum-one/meta-proxy` and check the asset list matches the requested patterns
  4. Unset RUFLO_DEV_PROXY_INSTALL to fall back to the default public-dist download path, which needs no gh

Example fix

# before
RUFLO_DEV_PROXY_INSTALL=1 ruflo proxy install   # gh release download failed (exit 1)
# after
gh auth login && gh release view -R cognitum-one/meta-proxy && \
  RUFLO_DEV_PROXY_INSTALL=1 ruflo proxy install
Defensive patterns

Strategy: validation

Validate before calling

import { spawnSync } from 'node:child_process';
const ghOk = spawnSync('gh', ['auth', 'status'], { encoding: 'utf8' }).status === 0;
if (process.env.RUFLO_DEV_PROXY_INSTALL && !ghOk) {
  throw new Error('dev install needs an authenticated gh CLI (run `gh auth login`)');
}

Type guard

const isGhDownloadFailure = (e: unknown): e is Error =>
  e instanceof Error && /^gh release download failed \(exit \d+\)/.test(e.message);

Try / catch

try {
  await installProxy({ version });
} catch (e) {
  if (isGhDownloadFailure(e)) {
    console.error(e.message); // gh's own stderr names the cause
    delete process.env.RUFLO_DEV_PROXY_INSTALL; // optionally fall back to the public-dist path
    return installProxy({ version });
  }
  throw e;
}

Prevention

When it happens

Trigger: gh CLI not installed (command-not-found exit code); gh present but never authenticated (`gh auth login` not run) against the repo; the release tag or the requested --pattern assets not found; network failure inside gh.

Common situations: Developers enabling RUFLO_DEV_PROXY_INSTALL on machines without gh; CI containers missing the gh binary; expired gh tokens; requesting an asset pattern for a triple the release does not contain.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/488dd9198d20dc43. Report an issue: GitHub.

Appendix: source

Thrown at v3/@claude-flow/cli/src/proxy/release.ts:121

  const exec = await ghExecutor();
  const result = await exec.execute('gh', [
    'release',
    'download',
    `v${version}`,
    '--repo',
    GH_REPO,
    '--dir',
    destDir,
    '--pattern',
    archiveFilename,
    '--pattern',
    'SHA256SUMS',
    '--pattern',
    'SHA256SUMS.sig',
    '--clobber',
  ]);
  if (result.exitCode !== 0) {
    throw new Error(`gh release download failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);
  }

  const { readFile } = await import('node:fs/promises');
  const { join } = await import('node:path');
  const [archiveBytes, sumsBytes, sigRaw] = await Promise.all([
    readFile(join(destDir, archiveFilename)),
    readFile(join(destDir, 'SHA256SUMS')),
    readFile(join(destDir, 'SHA256SUMS.sig'), 'utf-8'),
  ]);
  return { archiveBytes, archiveFilename, sumsBytes, sigBase64: sigRaw.trim() };
}

/**
 * Production download path — a Cognitum-owned, auth-mediated release-proxy
 * endpoint. Not implemented: no such endpoint exists in the confirmed
 * OpenAPI contract today. Throws a clear, specific error rather than
 * silently falling back to the dev path, so a real user hitting this isn't
 * left guessing whether it's their environment or a genuine gap.

View on GitHub (pinned to fa13ee4ad6)