ruvnet/ruflo · error
Pinata list failed (HTTP )
Error message
Pinata list failed (HTTP ${res.status}): ${JSON.stringify(res.data)} What it means
GET /data/pinList?status=pinned returned non-200; the message embeds the status code and response body. In practice dominated by 401 (expired or invalid JWT), with 429 rate-limiting and 5xx incidents as the transient cases. Only this list endpoint is involved — pinning/fetching can still work if the cause is request-rate.
Solutions
- 401 → regenerate the JWT and update PINATA_API_JWT
- 429 → slow the polling cadence and cache the result between calls
- Verify any apiUrl override is the correct Pinata base URL
- Check status.pinata.cloud for ongoing incidents when 5xx
Defensive patterns
Strategy: retry
Validate before calling
let cached: PublishedItem[] | null = null;
let lastList = 0;
async function listThrottled(p: RvfaPublisher): Promise<PublishedItem[]> {
if (cached && Date.now() - lastList < 60_000) return cached; // avoid rate limits
cached = await p.list();
lastList = Date.now();
return cached;
} Try / catch
try {
await publisher.list();
} catch (e) {
const msg = String(e);
if (/HTTP 401/.test(msg)) throw new Error('Pinata JWT expired — rotate PINATA_API_JWT');
if (/HTTP (429|5\d\d)/.test(msg)) { /* backoff and retry once */ }
else throw e;
} Prevention
- Cache pinList results and poll at a slow cadence instead of per-request
- Rotate JWTs on a schedule and alert before expiry
- Verify any apiUrl override points at the live Pinata API base
When it happens
Trigger: `publisher.list()` with a revoked or expired JWT; frequent polling of list() tripping rate limits; a custom apiUrl that is wrong or targets a deprecated Pinata API host.
Common situations: Same JWT lifecycle problems as upload failures; dashboards or scripts that poll pinList every few seconds; API base URL overrides that drift from https://api.pinata.cloud.
Related errors
- Pinata pin failed (HTTP )
- Pinata upload failed
- Pinata JWT required (config.pinataJwt or PINATA_API_JWT)
- Pinata upload failed
- Local IPFS upload failed
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/8cd0df5ec09ba733.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/appliance/rvfa-distribution.ts:377
}
async publishPatch(patchBuf: Buffer, meta?: PublishMetadata): Promise<PublishResult> {
const name = meta?.name || `patch-${Date.now()}.rvfp`;
return this.upload(name, patchBuf, {
type: 'rvfp-patch', version: meta?.version || '', description: meta?.description || '',
});
}
async fetch(cid: string, outputPath: string): Promise<void> {
const data = await httpGet(`${this.gw}/ipfs/${cid}`);
await mkdir(dirname(outputPath), { recursive: true });
await writeFile(outputPath, data);
}
async list(): Promise<PublishedItem[]> {
const res = await pinataReq('GET', `${this.api}/data/pinList?status=pinned&pageLimit=100`, this.jwt);
if (res.status !== 200)
throw new Error(`Pinata list failed (HTTP ${res.status}): ${JSON.stringify(res.data)}`);
const d = res.data as { rows: Array<{
ipfs_pin_hash: string; metadata?: { name?: string }; size: number; date_pinned: string;
}> };
return (d.rows || []).map((r) => ({
cid: r.ipfs_pin_hash, name: r.metadata?.name || r.ipfs_pin_hash,
size: r.size, date: r.date_pinned,
}));
}
async pin(cid: string, name?: string): Promise<void> {
const body = Buffer.from(JSON.stringify({ hashToPin: cid, pinataMetadata: { name: name || cid } }));
const res = await pinataReq('POST', `${this.api}/pinning/pinByHash`, this.jwt, body, 'application/json');
if (res.status !== 200)
throw new Error(`Pinata pin failed (HTTP ${res.status}): ${JSON.stringify(res.data)}`);
}
}
// ── Convenience exports ──────────────────────────────────────View on GitHub (pinned to fa13ee4ad6)