ruvnet/ruflo · error · Error
Pinata JWT required (config.pinataJwt or PINATA_API_JWT)
Error message
Pinata JWT required (config.pinataJwt or PINATA_API_JWT)
What it means
Thrown by the RvfaPublisher constructor when no Pinata JWT is available — neither in the passed PublishConfig.pinataJwt nor in the PINATA_API_JWT environment variable. The JWT is required as a Bearer token for every Pinata API call (upload, list, pin), so the publisher refuses to construct without it rather than failing on the first request.
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 6b01dc5a68)
Solutions
- Export PINATA_API_JWT in the environment before running the CLI: export PINATA_API_JWT=eyJ... (obtain from Pinata dashboard > Keys).
- Pass it explicitly: new RvfaPublisher({ pinataJwt: process.env.MY_JWT }).
- If using a .env file, ensure it is loaded (e.g. dotenv) before constructing the publisher.
- Confirm the JWT is a valid Pinata API JWT, not an API key + secret pair (v1 vs v2 auth).
Example fix
// before
const pub = createPublisher(); // throws if PINATA_API_JWT unset
// after
const pub = createPublisher({ pinataJwt: process.env.PINATA_API_JWT });
// or: export PINATA_API_JWT=eyJ... before running the process Defensive patterns
Strategy: validation
Validate before calling
function resolvePinataJwt(config?: { pinataJwt?: string }): string | null {
return config?.pinataJwt || process.env.PINATA_API_JWT || null;
}
const jwt = resolvePinataJwt();
if (!jwt) {
throw new Error('Set PINATA_API_JWT env var or pass pinataJwt before constructing RvfaPublisher');
} Try / catch
try {
const pub = new RvfaPublisher(config);
} catch (e) {
if (/Pinata JWT required/.test((e as Error).message)) {
throw new Error('No Pinata JWT found. Obtain one at https://app.pinata.cloud/keys and export PINATA_API_JWT');
}
throw e;
} Prevention
- Always export PINATA_API_JWT in the shell or CI secret store before running publishing commands.
- Load .env files (e.g. via dotenv) before constructing the publisher.
- Use a Pinata v2 API JWT (not the legacy apiKey+apiSecret pair).
- Fail fast at startup with a clear message if the JWT is missing.
When it happens
Trigger: Constructing new RvfaPublisher({}) or createPublisher() without setting PINATA_API_JWT and without passing pinataJwt. Running in a CI/CD shell or container where the env var was not propagated, or calling createPublisher() in a fresh process.
Common situations: Local dev without the env var exported; deploy manifests that stripped secrets; the JWT was stored in a .env that was not loaded; a typo in the variable name (PINATA_JWT vs PINATA_API_JWT).
Related errors
- User token not found
- MCP server "${server.name}" returned HTTP ${httpStatus}: ${h
- 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@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/ebea51634577b689.
Report an issue: GitHub.