{"record":{"id":"ca39ac616f672945","repo":"ruvnet/ruflo","slug":"failed-to-fetch-manifest-from-url-res-status","errorCode":null,"errorMessage":"Failed to fetch manifest from ${url}: ${res.status} ${res.statusText}","messagePattern":"Failed to fetch manifest from (.+?): (.+?) (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/commands/verify.ts","lineNumber":63,"sourceCode":"  integrity: {\n    manifestHashAlgo: string;\n    manifestHash: string;\n    signatureAlgo: string;\n    publicKey: string;\n    signature: string;\n    seedDerivation: string;\n  };\n}\n\nconst DEFAULT_MANIFEST_URL = 'https://raw.githubusercontent.com/ruvnet/ruflo/{branch}/verification.md.json';\n\nasync function fetchWitness(branch: string): Promise<Witness> {\n  const url = DEFAULT_MANIFEST_URL.replace('{branch}', branch);\n  // audit_1776853149979: bare fetch had no timeout — a hung GitHub CDN would\n  // pin the verify command indefinitely. 30s is generous for a sub-MB JSON.\n  const res = await fetch(url, { signal: AbortSignal.timeout(30000) });\n  if (!res.ok) {\n    throw new Error(`Failed to fetch manifest from ${url}: ${res.status} ${res.statusText}`);\n  }\n  return await res.json() as Witness;\n}\n\nfunction loadLocalWitness(localPath: string): Witness {\n  if (!existsSync(localPath)) {\n    throw new Error(`Manifest not found: ${localPath}`);\n  }\n  return JSON.parse(readFileSync(localPath, 'utf-8')) as Witness;\n}\n\n/**\n * Locate the user's installed package root.\n *\n * The witness manifest paths are repo-relative (e.g.\n * \"v3/@claude-flow/cli/dist/src/mcp-tools/hooks-tools.js\"). For\n * end users, only the dist/ subtree ships in node_modules. We map\n * the repo path → the installed equivalent by stripping the","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/cli/src/commands/verify.ts#L45-L81","documentation":"Thrown by fetchWitness() when the HTTP response to the witness-manifest fetch is not ok (res.ok === false). The fetch itself has a 30s AbortSignal timeout (added in audit_1776853149979 to avoid indefinite hangs), so this error specifically means the request completed but GitHub returned a non-2xx status.","triggerScenarios":"The target branch does not exist (404), the repo/manifest path moved (404), GitHub returned 5xx during an incident, rate-limiting (403/429), or network middleware rewriting the response.","commonSituations":"Verifying against a branch name that was renamed/deleted, running verify right after a push before the raw.githubusercontent.com cache updates, corporate proxy returning a block page (200 with HTML, or 4xx), or GitHub outage.","solutions":["Confirm the branch exists and contains verification.md.json at the expected path.","Retry shortly after a push — raw.githubusercontent.com has a short cache propagation delay.","If GitHub is unreachable, supply a local manifest with the --local flag (loadLocalWitness path).","Check rate-limit headers if you are scripting many verify calls."],"exampleFix":"// before\nruflo verify --branch feature/renamed\n// after\nruflo verify --branch main\n# or use a local manifest:\nruflo verify --local ./verification.md.json","handlingStrategy":"retry","validationCode":"async function fetchWitnessWithRetry(branch: string, attempts = 3): Promise<Witness> {\n  for (let i = 0; i < attempts; i++) {\n    const res = await fetch(urlFor(branch), { signal: AbortSignal.timeout(30000) });\n    if (res.ok) return await res.json();\n    if (res.status === 404) throw new Error(`branch ${branch} has no manifest`);\n    await new Promise(r => setTimeout(r, 500 * (i + 1)));\n  }\n  throw new Error(`manifest fetch failed after ${attempts} attempts`);\n}","typeGuard":"const isOkResponse = (res: Response): boolean => res.ok;","tryCatchPattern":"try {\n  await fetchWitness(branch);\n} catch (e) {\n  const msg = e instanceof Error ? e.message : String(e);\n  if (msg.startsWith('Failed to fetch manifest')) {\n    // fall back to a local manifest instead of retrying network blindly\n    return loadLocalWitness('./verification.md.json');\n  }\n  throw e;\n}","preventionTips":["Confirm the branch exists before verifying against it.","Wait a few seconds after a push for raw.githubusercontent.com cache to clear.","Keep a local manifest as a fallback for air-gapped/proxied environments."],"tags":["network","http","verify","supply-chain"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}