{"record":{"id":"90042a0e4ffe40c4","repo":"ruvnet/ruflo","slug":"local-ipfs-upload-failed-response-status-err","errorCode":null,"errorMessage":"Local IPFS upload failed: ${response.status} ${error}","messagePattern":"Local IPFS upload failed: (.+?) (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/transfer/ipfs/upload.ts","lineNumber":446,"sourceCode":"  const body = Buffer.concat([\n    Buffer.from(`--${boundary}\\r\\n`),\n    Buffer.from(`Content-Disposition: form-data; name=\"file\"; filename=\"${name}\"\\r\\n`),\n    Buffer.from(`Content-Type: application/json\\r\\n\\r\\n`),\n    content,\n    Buffer.from(`\\r\\n--${boundary}--\\r\\n`),\n  ]);\n\n  const response = await fetch(`${apiUrl}/api/v0/add?pin=${options.pin !== false}`, {\n    method: 'POST',\n    headers: {\n      'Content-Type': `multipart/form-data; boundary=${boundary}`,\n    },\n    body,\n  });\n\n  if (!response.ok) {\n    const error = await response.text();\n    throw new Error(`Local IPFS upload failed: ${response.status} ${error}`);\n  }\n\n  const result = await response.json() as { Hash: string; Size: string; Name: string };\n  const cid = result.Hash;\n\n  // Try to get external gateway URL if configured\n  const gatewayUrl = process.env.IPFS_GATEWAY_URL || options.gateway || 'https://ipfs.io';\n\n  console.log(`[IPFS] Upload complete!`);\n  console.log(`[IPFS] CID: ${cid}`);\n\n  return {\n    cid,\n    size: content.length,\n    gateway: gatewayUrl,\n    pinnedAt: options.pin !== false ? new Date().toISOString() : undefined,\n    url: `${gatewayUrl}/ipfs/${cid}`,\n  };","sourceCodeStart":428,"sourceCodeEnd":464,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/cli/src/transfer/ipfs/upload.ts#L428-L464","documentation":"The local-IPFS path POSTs to `${apiUrl}/api/v0/add` where apiUrl = process.env.IPFS_API_URL || 'http://localhost:5001' — i.e. the Kubo RPC API of your own node. This error means the node answered HTTP but returned a non-ok status; it is not a connection-refused error (a down node makes fetch itself reject with TypeError instead). Common causes: the daemon is running but the repo is locked (another ipfs daemon instance), the API is bound read-only, or the add request is malformed for that node.","triggerScenarios":"Uploading with provider 'local'/custom while two ipfs daemon processes fight over the same repo (repo lock -> 500); IPFS_API_URL pointing at a gateway port (8080) or read-only API instead of the RPC port 5001; a proxy in front of the API rejecting the multipart POST; node version whose /api/v0/add requires different params.","commonSituations":"'ipfs daemon run twice' (stale lock from a crashed daemon); port confusion between Gateway (8080) and API (5001); remote nodes secured behind auth proxies; dockerized ipfs where the API is not exposed.","solutions":["Confirm the node is healthy: curl http://localhost:5001/api/v0/id (or ipfs id) — if that also errors, fix the daemon first","If the repo is locked, remove the stale lock: kill stray ipfs processes, then delete <ipfs repo>/repo.lock and restart ipfs daemon","Point IPFS_API_URL at the RPC API (default http://localhost:5001), not the gateway port 8080","For persistent failures, fall back to a pinning provider (web3.storage/pinata)"],"exampleFix":"# before\nIPFS_API_URL=http://localhost:8080 npx claude-flow hooks transfer store --provider local\n# gateway port answers the RPC route with an error -> Local IPFS upload failed: 404 ...\n\n# after\nipfs daemon &  # ensure single healthy daemon\nexport IPFS_API_URL=http://localhost:5001\ncurl -s http://localhost:5001/api/v0/id  # sanity check before upload","handlingStrategy":"retry","validationCode":"// Preflight: the Kubo RPC API must answer /api/v0/id before uploading\nconst apiUrl = process.env.IPFS_API_URL || 'http://localhost:5001';\nconst probe = await fetch(`${apiUrl}/api/v0/id`, { method: 'POST' });\nif (!probe.ok) {\n  throw new Error(`Local IPFS node unhealthy (${apiUrl}): ${probe.status} — start/repair 'ipfs daemon' before upload`);\n}\nawait uploadToIPFS(content, { provider: 'local' });","typeGuard":null,"tryCatchPattern":"try {\n  result = await uploadToIPFS(content, { provider: 'local' });\n} catch (e) {\n  if (!/Local IPFS upload failed/.test(String((e as Error)?.message))) throw e;\n  // node answered HTTP but errored: fix daemon (repo lock, wrong port) then retry once\n  await new Promise(r => setTimeout(r, 1_000));\n  result = await uploadToIPFS(content, { provider: 'local' });\n}","preventionTips":["Point IPFS_API_URL at the RPC API port (5001), never the gateway port (8080)","Health-check the node with POST /api/v0/id before batch uploads","Run exactly one ipfs daemon per repo; clean repo.lock after crashes"],"tags":["ipfs","local-node","http","upload","kubo","daemon"],"backgroundTag":"http-request-failed","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}