You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

执行yarn start上传文件至Pinata失败,报错FORBIDDEN请求排查

Pinata上传失败:账户因套餐使用限制被封禁问题排查

执行yarn start命令时无法将文件上传至Pinata平台,虽认为自身套餐支持该操作,但仍出现错误。以下是相关代码及报错信息:

app.ts代码

import * as dotenv from "dotenv";

import { toNano } from "ton-core";
import { readdir } from "fs/promises";

import { openWallet } from "./utils";
import { waitSeqno } from "./delay";
import { NftCollection } from "./contracts/NftCollection";
import { NftItem } from "./contracts/NftItem";
import { updateMetadataFiles, uploadFolderToIPFS } from "./metadata";
import { GetGemsSaleData, NftSale } from "./contracts/NftSale";
import { NftMarketplace } from "./contracts/NftMarketplace";

dotenv.config();

async function init() {
  try {
    const metadataFolderPath = "./data/metadata/";
    const imagesFolderPath = "./data/images/";

    const wallet = await openWallet(process.env.MNEMONIC!.split(" "), true);

    console.log("Started uploading images to IPFS...");
    const imagesIpfsHash = await uploadFolderToIPFS(imagesFolderPath);
    console.log(
      `Successfully uploaded the pictures to ipfs: https://gateway.pinata.cloud/ipfs/${imagesIpfsHash}`
    );

    console.log("Started uploading metadata files to IPFS...");
    await updateMetadataFiles(metadataFolderPath, imagesIpfsHash);
    const metadataIpfsHash = await uploadFolderToIPFS(metadataFolderPath);
    console.log(
      `Successfully uploaded the metadata to ipfs: https://gateway.pinata.cloud/ipfs/${metadataIpfsHash}`
    );

    console.log("Start deploy of nft collection...");
    const collectionData = {
      ownerAddress: wallet.contract.address,
      royaltyPercent: 0.05, // 0.05 = 5%
      royaltyAddress: wallet.contract.address,
      nextItemIndex: 0,
      collectionContentUrl: `ipfs://${metadataIpfsHash}/collection.json`,
      commonContentUrl: `ipfs://${metadataIpfsHash}/`,
    };
    const collection = new NftCollection(collectionData);
    let seqno = await collection.deploy(wallet);
    console.log(`Collection deployed: ${collection.address}`);
    await waitSeqno(seqno, wallet);

    // Deploy nft items
    const files = await readdir(metadataFolderPath);
    files.pop();
    let index = 0;

    seqno = await collection.topUpBalance(wallet, files.length);
    await waitSeqno(seqno, wallet);
    console.log(`Balance top-upped`);

    for (const file of files) {
      try {
        console.log(`Start deploy of ${index + 1} NFT`);
        const mintParams = {
          queryId: 0,
          itemOwnerAddress: wallet.contract.address,
          itemIndex: index,
          amount: toNano("0.05"),
          commonContentUrl: file,
        };
        const nftItem = new NftItem(collection);
        seqno = await nftItem.deploy(wallet, mintParams);
        console.log(`Successfully deployed ${index + 1} NFT`);
        await waitSeqno(seqno, wallet);
        index++;
      } catch (error) {
        console.error(`Error deploying ${index + 1} NFT:`, error);
      }
    }

    console.log("Start deploy of new marketplace  ");
    const marketplace = new NftMarketplace(wallet.contract.address);
    seqno = await marketplace.deploy(wallet);
    await waitSeqno(seqno, wallet);
    console.log("Successfully deployed new marketplace");

    try {
      const nftToSaleAddress = await NftItem.getAddressByIndex(collection.address, 0);
      const saleData: GetGemsSaleData = {
        isComplete: false,
        createdAt: Math.ceil(Date.now() / 1000),
        marketplaceAddress: marketplace.address,
        nftAddress: nftToSaleAddress,
        nftOwnerAddress: null,
        fullPrice: toNano("10"),
        marketplaceFeeAddress: wallet.contract.address,
        marketplaceFee: toNano("1"),
        royaltyAddress: wallet.contract.address,
        royaltyAmount: toNano("0.5"),
      };
      const nftSaleContract = new NftSale(saleData);
      seqno = await nftSaleContract.deploy(wallet);
      await waitSeqno(seqno, wallet);

    } catch (error) {
      console.error('Error setting up NFT for sale:', error);
    }
  } catch (error) {
    console.error('Initialization failed:', error);
  }
}

void init();

报错信息

% yarn start
yarn run v1.22.19
$ tsc --skipLibCheck && node dist/app.js
Started uploading images to IPFS...
Initialization failed: {
reason: 'FORBIDDEN',
details: 'Account blocked due to plan usage limit'
}
✨  Done in 3.96s.

排查步骤

  • 核实套餐额度:登录Pinata后台,查看当前存储容量、月度上传流量等是否已达套餐上限。免费版通常有明确的额度限制,比如总存储、每日上传次数。
  • 检查API密钥状态:确认项目中使用的Pinata API密钥是否正确、未被禁用。密钥可能因额度耗尽或违规操作被临时限制。
  • 验证上传内容规格:检查要上传的图片/元数据文件夹总大小,确认是否超出套餐单文件或总文件大小限制(比如免费版单文件可能限1GB)。
  • 查看账户通知:登录Pinata账户,查看是否有官方发送的额度预警或违规封禁通知,确认是否存在违规内容上传导致的限制。
  • 测试基础上传:手动通过Pinata网页端上传单个小文件,验证账户是否能正常操作。若网页端也无法上传,说明账户确实受限,需联系官方支持或升级套餐。
  • 检查上传逻辑:确认uploadFolderToIPFS函数是否一次性上传过大内容,可尝试拆分上传少量文件测试是否触发限制。

内容的提问来源于stack exchange,提问作者user24786531

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 00:27:23