ruvnet/ruflo · error · Error
Local IPFS upload failed: ${response.status} ${error}
Error message
Local IPFS upload failed: ${response.status} ${error} What it means
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.
Source
Thrown at v3/@claude-flow/cli/src/transfer/ipfs/upload.ts:446
const body = Buffer.concat([
Buffer.from(`--${boundary}\r\n`),
Buffer.from(`Content-Disposition: form-data; name="file"; filename="${name}"\r\n`),
Buffer.from(`Content-Type: application/json\r\n\r\n`),
content,
Buffer.from(`\r\n--${boundary}--\r\n`),
]);
const response = await fetch(`${apiUrl}/api/v0/add?pin=${options.pin !== false}`, {
method: 'POST',
headers: {
'Content-Type': `multipart/form-data; boundary=${boundary}`,
},
body,
});
if (!response.ok) {
const error = await response.text();
throw new Error(`Local IPFS upload failed: ${response.status} ${error}`);
}
const result = await response.json() as { Hash: string; Size: string; Name: string };
const cid = result.Hash;
// Try to get external gateway URL if configured
const gatewayUrl = process.env.IPFS_GATEWAY_URL || options.gateway || 'https://ipfs.io';
console.log(`[IPFS] Upload complete!`);
console.log(`[IPFS] CID: ${cid}`);
return {
cid,
size: content.length,
gateway: gatewayUrl,
pinnedAt: options.pin !== false ? new Date().toISOString() : undefined,
url: `${gatewayUrl}/ipfs/${cid}`,
};View on GitHub (pinned to fa13ee4ad6)
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)
Example fix
# before IPFS_API_URL=http://localhost:8080 npx claude-flow hooks transfer store --provider local # gateway port answers the RPC route with an error -> Local IPFS upload failed: 404 ... # after ipfs daemon & # ensure single healthy daemon export IPFS_API_URL=http://localhost:5001 curl -s http://localhost:5001/api/v0/id # sanity check before upload
Defensive patterns
Strategy: retry
Validate before calling
// Preflight: the Kubo RPC API must answer /api/v0/id before uploading
const apiUrl = process.env.IPFS_API_URL || 'http://localhost:5001';
const probe = await fetch(`${apiUrl}/api/v0/id`, { method: 'POST' });
if (!probe.ok) {
throw new Error(`Local IPFS node unhealthy (${apiUrl}): ${probe.status} — start/repair 'ipfs daemon' before upload`);
}
await uploadToIPFS(content, { provider: 'local' }); Try / catch
try {
result = await uploadToIPFS(content, { provider: 'local' });
} catch (e) {
if (!/Local IPFS upload failed/.test(String((e as Error)?.message))) throw e;
// node answered HTTP but errored: fix daemon (repo lock, wrong port) then retry once
await new Promise(r => setTimeout(r, 1_000));
result = await uploadToIPFS(content, { provider: 'local' });
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: '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.
Related errors
- Web3.storage upload failed: ${response.status} ${error}
- Pinata upload failed: ${response.status} ${error}
- Pinata upload failed (HTTP ${res.status}): ${JSON.stringify(
- Pinata list failed (HTTP ${res.status}): ${JSON.stringify(re
- Pinata pin failed (HTTP ${res.status}): ${JSON.stringify(res
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/90042a0e4ffe40c4.
Report an issue: GitHub.