{"record":{"id":"508e584c6332167c","repo":"ruvnet/ruflo","slug":"pinata-pin-failed-http-res-status-json-str","errorCode":null,"errorMessage":"Pinata pin failed (HTTP ${res.status}): ${JSON.stringify(res.data)}","messagePattern":"Pinata pin failed \\(HTTP (.+?)\\): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/appliance/rvfa-distribution.ts","lineNumber":391,"sourceCode":"\n  async list(): Promise<PublishedItem[]> {\n    const res = await pinataReq('GET', `${this.api}/data/pinList?status=pinned&pageLimit=100`, this.jwt);\n    if (res.status !== 200)\n      throw new Error(`Pinata list failed (HTTP ${res.status}): ${JSON.stringify(res.data)}`);\n    const d = res.data as { rows: Array<{\n      ipfs_pin_hash: string; metadata?: { name?: string }; size: number; date_pinned: string;\n    }> };\n    return (d.rows || []).map((r) => ({\n      cid: r.ipfs_pin_hash, name: r.metadata?.name || r.ipfs_pin_hash,\n      size: r.size, date: r.date_pinned,\n    }));\n  }\n\n  async pin(cid: string, name?: string): Promise<void> {\n    const body = Buffer.from(JSON.stringify({ hashToPin: cid, pinataMetadata: { name: name || cid } }));\n    const res = await pinataReq('POST', `${this.api}/pinning/pinByHash`, this.jwt, body, 'application/json');\n    if (res.status !== 200)\n      throw new Error(`Pinata pin failed (HTTP ${res.status}): ${JSON.stringify(res.data)}`);\n  }\n}\n\n// ── Convenience exports ──────────────────────────────────────\nexport function createPublisher(config?: Partial<PublishConfig>): RvfaPublisher {\n  return new RvfaPublisher({ pinataJwt: config?.pinataJwt, gatewayUrl: config?.gatewayUrl, apiUrl: config?.apiUrl });\n}\n\nexport async function createAndVerifyPatch(\n  options: CreatePatchOptions,\n): Promise<{ patch: Buffer; verification: PatchVerifyResult }> {\n  const patch = await RvfaPatcher.createPatch(options);\n  const verification = await RvfaPatcher.verifyPatch(patch);\n  return { patch, verification };\n}\n","sourceCodeStart":373,"sourceCodeEnd":407,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/cli/src/appliance/rvfa-distribution.ts#L373-L407","documentation":"POST /pinning/pinByHash returned non-200; the message embeds status and body. pinByHash asks Pinata to pin content already on IPFS by CID, so failures are typically 400 for a malformed CID, 401 for credential problems, or 402/403 plan limits. The CID is passed verbatim from the caller, so format errors upstream land here.","triggerScenarios":"`publisher.pin(cid)` with a CID carrying an `ipfs://` prefix, a typo, or wrong base encoding (400); an expired JWT (401); pin quota reached (402/403).","commonSituations":"Copying CIDs with the ipfs:// scheme attached; truncated base32 CIDs from logs; assuming content is reachable when no IPFS node actually holds it.","solutions":["Normalize the CID first: strip ipfs:// and validate the format (Qm... base58 or bafy... base32)","401 → refresh the JWT","402/403 → free pin slots by unpinning old content or upgrade the plan","Confirm the content is actually retrievable (gateway fetch) before pinning by hash"],"exampleFix":"// before\nawait publisher.pin(`ipfs://${cid}`); // prefix breaks CID parsing → HTTP 400\n\n// after\nconst cleanCid = cid.replace(/^ipfs:\\/\\//, '');\nawait publisher.pin(cleanCid);","handlingStrategy":"retry","validationCode":"const cleanCid = cid.replace(/^ipfs:\\/\\//, '');\nconst valid = /^(Qm[1-9A-HJ-NP-Za-km-z]{44}|baf[a-z0-9]+)$/.test(cleanCid);\nif (!valid) throw new Error(`Invalid CID: ${cid}`);\nawait publisher.pin(cleanCid);","typeGuard":"function isValidCid(cid: string): boolean {\n  const c = cid.replace(/^ipfs:\\/\\//, '');\n  return /^Qm[1-9A-HJ-NP-Za-km-z]{44}$/.test(c) || /^baf[a-z0-9]{20,}$/.test(c);\n}","tryCatchPattern":"try {\n  await publisher.pin(cleanCid);\n} catch (e) {\n  const msg = String(e);\n  if (/HTTP 400/.test(msg)) throw new Error(`Pinata rejected CID \"${cleanCid}\" — malformed or unpinable`);\n  if (/HTTP (429|5\\d\\d)/.test(msg)) { /* transient — retry with backoff */ }\n  else throw e;\n}","preventionTips":["Strip ipfs:// prefixes and validate CID shape (Qm... base58 / bafy... base32) before calling pin()","Confirm content is retrievable via a gateway before pinning by hash","Retry only transient statuses; a 400 CID rejection will never succeed on retry"],"tags":["rvfa-distribution","pinata","ipfs","cid","http"],"backgroundTag":"http-api-error","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}