{"record":{"id":"070496c5348b70f7","repo":"ruvnet/ruflo","slug":"pinata-api-credentials-not-found-set-pinata-api-k","errorCode":null,"errorMessage":"Pinata API credentials not found. Set PINATA_API_KEY and PINATA_API_SECRET.\nGet credentials at: https://pinata.cloud","messagePattern":"Pinata API credentials not found\\. Set PINATA_API_KEY and PINATA_API_SECRET\\.\nGet credentials at: https://pinata\\.cloud","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/transfer/ipfs/upload.ts","lineNumber":145,"sourceCode":"    size: content.length,\n    gateway,\n    pinnedAt: new Date().toISOString(),\n    url: `${gateway}/ipfs/${cid}`,\n  };\n}\n\n/**\n * Upload to Pinata\n */\nasync function uploadToPinata(\n  content: Buffer,\n  options: IPFSUploadOptions\n): Promise<IPFSUploadResult> {\n  const apiKey = options.apiKey || process.env.PINATA_API_KEY;\n  const apiSecret = options.apiSecret || process.env.PINATA_API_SECRET;\n\n  if (!apiKey || !apiSecret) {\n    throw new Error(\n      'Pinata API credentials not found. Set PINATA_API_KEY and PINATA_API_SECRET.\\n' +\n      'Get credentials at: https://pinata.cloud'\n    );\n  }\n\n  const name = options.name || 'pattern.cfp.json';\n  console.log(`[IPFS] Uploading ${content.length} bytes to Pinata...`);\n\n  const boundary = '----WebKitFormBoundary' + crypto.randomBytes(16).toString('hex');\n  const metadata = JSON.stringify({ name });\n\n  const body = Buffer.concat([\n    Buffer.from(`--${boundary}\\r\\n`),\n    Buffer.from(`Content-Disposition: form-data; name=\"pinataMetadata\"\\r\\n\\r\\n`),\n    Buffer.from(`${metadata}\\r\\n`),\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`),","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/cli/src/transfer/ipfs/upload.ts#L127-L163","documentation":"uploadToPinata() requires an API key pair: options.apiKey/options.apiSecret, falling back to PINATA_API_KEY and PINATA_API_SECRET env vars. If either is missing it throws before building the multipart request, pointing at https://pinata.cloud for credentials. Both values are required — one without the other still fails.","triggerScenarios":"Calling uploadToIPFS(content, { provider: 'pinata' }) with only PINATA_API_KEY set (secret missing); neither variable set in the process; passing options.apiKey without options.apiSecret programmatically.","commonSituations":"Partial credential setup (key copied, secret forgotten); env vars not exported to CI shells; rotating Pinata credentials and updating only one variable; switching from web3.storage to pinata without configuring the new pair.","solutions":["Set both: export PINATA_API_KEY=... and export PINATA_API_SECRET=... (from https://pinata.cloud) and rerun","Or supply both programmatically: uploadToIPFS(content, { provider: 'pinata', apiKey, apiSecret })","Verify both variables are visible: node -e \"console.log(!!process.env.PINATA_API_KEY, !!process.env.PINATA_API_SECRET)\"","Prefer the alternate provider set if you only have web3/local-node credentials configured"],"exampleFix":"# before\nexport PINATA_API_KEY=xyz # secret missing -> Pinata API credentials not found\n\n# after\nexport PINATA_API_KEY=xyz\nexport PINATA_API_SECRET=abc\nnpx claude-flow hooks transfer store --provider pinata","handlingStrategy":"validation","validationCode":"const apiKey = options.apiKey ?? process.env.PINATA_API_KEY;\nconst apiSecret = options.apiSecret ?? process.env.PINATA_API_SECRET;\nif (!apiKey || !apiSecret) {\n  throw new Error('pinata provider selected but credentials incomplete (need PINATA_API_KEY and PINATA_API_SECRET)');\n}\nawait uploadToIPFS(content, { provider: 'pinata', ...options });","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check both variables together — the API needs the pair, one alone always fails","Add a startup assertion listing every provider env var your deployment requires","After rotating Pinata keys, update both variables in every environment that runs transfers"],"tags":["ipfs","pinata","environment-variable","authentication","upload"],"backgroundTag":"missing-environment-variable","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}