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

Circle CI通过SFTP部署Nuxt项目失败问题求助

Nuxt项目Circle CI部署SFTP上传失败问题修复建议

问题背景

此前数月使用Circle CI部署Nuxt项目到服务器均正常,两天前Circle CI出现故障后,SFTP上传环节开始失败。部署脚本与错误日志如下:

部署脚本

require('dotenv').config();
console.log("Starting upload")
var SftpUpload = require('sftp-upload'),
    fs = require('fs');

var options = {
    host: process.env.FTP_HOST,
    username: process.env.FTP_UN,
    password: process.env.FTP_PW,
    path: './dist',
    remoteDir: process.env.FTP_PATH,
    dryRun: false,
}

console.log(options);
sftp = new SftpUpload(options);

console.log("sftp working ahead")

sftp.on('error', function(err) {
    console.log(options)
    console.log("igoring error for now")
    //throw err;
})
.on('uploading', function(progress) {
    console.log(options);
    console.log('Uploading', progress.file);
    console.log(progress.percent+'% completed');
})
.on('completed', function() {
    console.log('Upload Completed');
})
.upload();

错误日志

Starting upload
{
  host: '************************',
  username: '*********',
  password: '************',
  path: './dist',
  remoteDir: '*****************************************',
  dryRun: false
}
sftp working ahead
buffer.js:330
  throw new ERR_INVALID_ARG_TYPE(
  ^

TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received undefined
    at Function.from (buffer.js:330:9)
    at new Buffer (buffer.js:286:17)
    at onNEWKEYS (/home/circleci/repo/node_modules/ssh2/lib/Connection.js:2282:29)
    at Parser.<anonymous> (/home/circleci/repo/node_modules/ssh2/lib/Connection.js:123:5)
    at Parser.emit (events.js:314:20)
    at Parser.parsePacket (/home/circleci/repo/node_modules/ssh2/lib/Parser.js:468:12)
    at Parser.execute (/home/circleci/repo/node_modules/ssh2/lib/Parser.js:249:14)
    at Socket.<anonymous> (/home/circleci/repo/node_modules/ssh2/lib/Connection.js:523:18)
    at Socket.emit (events.js:314:20)
    at addChunk (_stream_readable.js:297:12) {
  code: 'ERR_INVALID_ARG_TYPE'
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! nyb.nyb.nyb@1.0.0 deploy: `node deploy-sftp.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the nyb.nyb.nyb@1.0.0 deploy script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/circleci/.npm/_logs/2022-09-16T08_55_31_507Z-debug.log


Exited with code exit status 1

CircleCI received exit code 1

问题分析

错误源于sftp-upload依赖的ssh2库在处理密钥交换(onNEWKEYS阶段)时,传入了undefined参数到Buffer构造函数,核心原因是库版本与Node.js版本不兼容:

  • Circle CI环境默认Node.js版本更新,旧版ssh2无法适配新版Node的Buffer API
  • 依赖安装时拉取了ssh2的更新版本,与停止维护的sftp-upload存在兼容性冲突

修复方案

方案1:锁定ssh2兼容版本

若需继续使用sftp-upload,可通过npm resolutions锁定兼容版本(需npm 7+支持):

  1. 在package.json中添加配置:
"resolutions": {
  "ssh2": "^0.8.9"
}
  1. 修改Circle CI依赖安装步骤为npm ci,确保依赖版本严格匹配package-lock.json
  2. 重新运行部署流水线

方案2:替换为维护活跃的SFTP库

sftp-upload已多年未更新,建议替换为ssh2-sftp-client,示例代码如下:

require('dotenv').config();
const Client = require('ssh2-sftp-client');
const fs = require('fs');
const path = require('path');

const sftp = new Client();
const config = {
  host: process.env.FTP_HOST,
  username: process.env.FTP_UN,
  password: process.env.FTP_PW
};

// 递归上传目录
async function uploadDir(localDir, remoteDir) {
  const items = fs.readdirSync(localDir, { withFileTypes: true });
  
  // 确保远程目录存在
  try {
    await sftp.stat(remoteDir);
  } catch {
    await sftp.mkdir(remoteDir, true);
  }

  for (const item of items) {
    const localPath = path.join(localDir, item.name);
    const remotePath = path.join(remoteDir, item.name);

    if (item.isDirectory()) {
      await uploadDir(localPath, remotePath);
    } else {
      await sftp.put(localPath, remotePath);
      console.log(`已上传: ${localPath} -> ${remotePath}`);
    }
  }
}

// 执行上传
sftp.connect(config)
  .then(() => uploadDir('./dist', process.env.FTP_PATH))
  .then(() => console.log('上传完成'))
  .catch(err => {
    console.error('上传失败:', err.message);
    process.exit(1);
  })
  .finally(() => sftp.end());

使用步骤:

  1. 安装新依赖:npm install ssh2-sftp-client --save-dev
  2. 替换原部署脚本为上述代码
  3. 重新运行部署流水线

方案3:固定Circle CI的Node.js版本

检查Circle CI配置文件(.circleci/config.yml),指定之前正常运行的Node.js版本,示例:

jobs:
  build:
    docker:
      - image: circleci/node:14.18.0 # 替换为之前正常使用的Node版本
    steps:
      - checkout
      - run: npm install
      - run: npm run generate
      - run: npm run deploy

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 11:55:23