ruvnet/ruflo · error · Error

Failed to fetch manifest from

Error message

Failed to fetch manifest from ${url}: ${res.status} ${res.statusText}

What it means

The verify command fetches the signed witness manifest (verification.md.json) from raw.githubusercontent.com for the target branch (default fix/issues-may-1-3). A non-2xx HTTP response throws with the status code and reason; the surrounding handler reports 'Could not load witness manifest: ...' and exits 1. The fetch carries a 30-second abort timeout, so hangs surface as timeout aborts, not this error.

Solutions

  1. Confirm the branch exists and contains verification.md.json at its root on GitHub
  2. Skip the network: download the manifest (or copy it from a release artifact) and pass --manifest ./verification.md.json
  3. From the same machine, curl -I the exact URL shown in the error to distinguish 404 vs proxy vs rate-limit
  4. If rate-limited (403), wait and retry, or use the local-manifest path in CI

Example fix

# before
ruflo verify --branch nonexistent-branch

# after
curl -fsSL -o verification.md.json https://raw.githubusercontent.com/ruvnet/ruflo/main/verification.md.json
ruflo verify --manifest ./verification.md.json
Defensive patterns

Strategy: retry

Validate before calling

const res = await fetch(manifestUrl, { signal: AbortSignal.timeout(10_000) });
if (!res.ok) throw new Error(`manifest fetch failed: ${res.status}`);
// pre-flight the URL yourself, or skip the network entirely with --manifest <local file>

Try / catch

for (const branch of ['main', 'fix/issues-may-1-3']) {
  try {
    witness = await fetchWitness(branch);
    break;
  } catch (err) {
    if (err instanceof Error && err.message.includes('Failed to fetch manifest')) continue;
    throw err;
  }
}
if (!witness) throw new Error('fall back to: ruflo verify --manifest ./verification.md.json');

Prevention

When it happens

Trigger: Passing --branch <name> for a branch that doesn't exist or lacks verification.md.json (404); GitHub raw CDN rate-limiting (403); a corporate proxy intercepting with 407/502.

Common situations: Verifying against an old tag whose manifest was never published; CI runners behind egress filters; regions where raw.githubusercontent.com is blocked.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at v3/@claude-flow/cli/src/commands/verify.ts:63

  integrity: {
    manifestHashAlgo: string;
    manifestHash: string;
    signatureAlgo: string;
    publicKey: string;
    signature: string;
    seedDerivation: string;
  };
}

const DEFAULT_MANIFEST_URL = 'https://raw.githubusercontent.com/ruvnet/ruflo/{branch}/verification.md.json';

async function fetchWitness(branch: string): Promise<Witness> {
  const url = DEFAULT_MANIFEST_URL.replace('{branch}', branch);
  // audit_1776853149979: bare fetch had no timeout — a hung GitHub CDN would
  // pin the verify command indefinitely. 30s is generous for a sub-MB JSON.
  const res = await fetch(url, { signal: AbortSignal.timeout(30000) });
  if (!res.ok) {
    throw new Error(`Failed to fetch manifest from ${url}: ${res.status} ${res.statusText}`);
  }
  return await res.json() as Witness;
}

function loadLocalWitness(localPath: string): Witness {
  if (!existsSync(localPath)) {
    throw new Error(`Manifest not found: ${localPath}`);
  }
  return JSON.parse(readFileSync(localPath, 'utf-8')) as Witness;
}

/**
 * Locate the user's installed package root.
 *
 * The witness manifest paths are repo-relative (e.g.
 * "v3/@claude-flow/cli/dist/src/mcp-tools/hooks-tools.js"). For
 * end users, only the dist/ subtree ships in node_modules. We map
 * the repo path → the installed equivalent by stripping the

View on GitHub (pinned to fa13ee4ad6)