ruvnet/ruflo · error
Pinata JWT required (config.pinataJwt or PINATA_API_JWT)
Error message
Pinata JWT required (config.pinataJwt or PINATA_API_JWT)
What it means
RvfaPublisher needs a Pinata JWT for every API call. The constructor resolves it from config.pinataJwt then env PINATA_API_JWT and throws immediately if both are empty — a pure credentials-wiring error; no network request is attempted.
Solutions
- export PINATA_API_JWT=... (create one at pinata.cloud under API Keys)
- Or pass it explicitly: createPublisher({ pinataJwt: process.env.PINATA_API_JWT! })
- Construct the publisher after env/config loading completes, not at import time
- Fail fast at boot with a clear message when the credential is absent
Example fix
// before
const publisher = createPublisher(); // no config, no env → throws
// after
const pinataJwt = process.env.PINATA_API_JWT;
if (!pinataJwt) throw new Error('PINATA_API_JWT not set — create a key at pinata.cloud');
const publisher = createPublisher({ pinataJwt }); Defensive patterns
Strategy: validation
Validate before calling
const pinataJwt = process.env.PINATA_API_JWT;
if (!pinataJwt) {
throw new Error('PINATA_API_JWT not set — create a key at pinata.cloud and export it');
}
const publisher = createPublisher({ pinataJwt }); Prevention
- Load .env before constructing the publisher; never construct it at import time
- Add a boot-time credential check listing every required env var (PINATA_API_JWT among them)
- Name the secret exactly PINATA_API_JWT, or pass pinataJwt explicitly in config
When it happens
Trigger: `new RvfaPublisher({})` or `createPublisher()` with PINATA_API_JWT unset; CI shells that never exported the variable; constructing the publisher at module load before .env is read; the JWT stored under a different variable name.
Common situations: Forgetting to source the env file; variable named PINATA_JWT or PINATA_KEY instead of PINATA_API_JWT; config object built before environment loading completes.
Related errors
- Pinata list failed (HTTP )
- Pinata pin failed (HTTP )
- Pinata upload failed
- Pinata API credentials not found. Set PINATA_API_KEY and…
- Pinata upload failed
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/ebea51634577b689.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/appliance/rvfa-distribution.ts:334
{ backupPath, newSize: newRvfa.length });
}
}
return { success: true, backupPath, newSize: newRvfa.length, patchedSection: sec, errors: [] };
}
}
// ── RvfaPublisher ────────────────────────────────────────────
export class RvfaPublisher {
private jwt: string;
private gw: string;
private api: string;
constructor(config: PublishConfig) {
this.jwt = config.pinataJwt || process.env.PINATA_API_JWT || '';
this.gw = (config.gatewayUrl || DEFAULT_GW).replace(/\/+$/, '');
this.api = (config.apiUrl || DEFAULT_API).replace(/\/+$/, '');
if (!this.jwt) throw new Error('Pinata JWT required (config.pinataJwt or PINATA_API_JWT)');
}
private async upload(
fileName: string, data: Buffer, kv: Record<string, string>,
): Promise<PublishResult> {
const meta = JSON.stringify({ name: fileName, keyvalues: kv });
const { body, ct } = multipart('file', fileName, data, meta);
const res = await pinataReq('POST', `${this.api}/pinning/pinFileToIPFS`, this.jwt, body, ct);
if (res.status !== 200)
throw new Error(`Pinata upload failed (HTTP ${res.status}): ${JSON.stringify(res.data)}`);
const r = res.data as { IpfsHash: string; PinSize: number };
return {
cid: r.IpfsHash, size: r.PinSize,
gatewayUrl: `${this.gw}/ipfs/${r.IpfsHash}`, pinataUrl: `${this.api}/pinning/pins/${r.IpfsHash}`,
};
}
async publish(rvfaPath: string, meta?: PublishMetadata): Promise<PublishResult> {View on GitHub (pinned to fa13ee4ad6)