oven-sh/bun · error

SCP failed: ${source} -> ${username}@${hostname}:${destinati

Error message

SCP failed: ${source} -> ${username}@${hostname}:${destination}

What it means

A retried scp (exponential backoff 2^i seconds) to username@hostname:destination exited non-zero on every attempt; the loop breaks early when stderr matches 'bad configuration option' or 'no such file or directory' (ssh/scp config or binary problems), otherwise it exhausts retries and throws with cause = last stderr.

Source

Thrown at scripts/machine.mjs:1000

    command.push(`${hostname}:${destination}`);
  }

  let cause;
  for (let i = 0; i < retries; i++) {
    const result = await spawn(command, { stdio: "inherit" });
    const { exitCode, stderr } = result;
    if (exitCode === 0) {
      return;
    }

    cause = stderr.trim() || undefined;
    if (/(bad configuration option)|(no such file or directory)/i.test(stderr)) {
      break;
    }
    await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
  }

  throw new Error(`SCP failed: ${source} -> ${username}@${hostname}:${destination}`, { cause });
}

/**
 * @param {string} passwordData
 * @param {string} privateKeyPath
 * @returns {string}
 */
function decryptPassword(passwordData, privateKeyPath) {
  const name = basename(privateKeyPath, extname(privateKeyPath));
  const tmpPemPath = mkdtemp("pem-", `${name}.pem`);
  try {
    copyFile(privateKeyPath, tmpPemPath, { mode: 0o600 });
    spawnSyncSafe(["ssh-keygen", "-p", "-m", "PEM", "-f", tmpPemPath, "-N", ""]);
    const { stdout } = spawnSyncSafe(
      ["openssl", "pkeyutl", "-decrypt", "-inkey", tmpPemPath, "-pkeyopt", "rsa_padding_mode:pkcs1"],
      {
        stdin: Buffer.from(passwordData, "base64"),
      },

View on GitHub (pinned to 8c5296ac45)

Solutions

  1. Inspect error.cause — it holds scp's trimmed stderr with the real reason
  2. Test connectivity first: `ssh user@host true`
  3. Fix or remove the offending ~/.ssh/config option if stderr mentions 'bad configuration option'
  4. Create the destination directory on the remote before scp, or wait for SSH readiness and retry

Example fix

// before
await scpTo(source, destination, machine);

// after
try {
  await scpTo(source, destination, machine);
} catch (err) {
  console.error('scp stderr:', err.cause);
  throw err;
}
Defensive patterns

Strategy: retry

Validate before calling

// Confirm SSH readiness before the first scp attempt
await $`ssh -o BatchMode=yes -o ConnectTimeout=10 ${username}@${hostname} true`;

Try / catch

try {
  await scpTo(source, destination, machine);
} catch (error) {
  const stderr = String(error.cause ?? '');
  if (/bad configuration option|no such file or directory/i.test(stderr)) {
    // local ssh/scp setup problem — fix ~/.ssh/config, do not retry
    throw error;
  }
  // otherwise: VM not ready yet — wait and retry (scpTo already backs off)
  throw error;
}

Prevention

When it happens

Trigger: Windows VM not yet accepting SSH after boot; wrong key or credentials; destination directory missing on the remote; an unsupported option in ~/.ssh/config; scp binary path problems on the local host.

Common situations: Provisioning racing VM readiness; typo'd destination path; updated OpenSSH where an old config option was removed; security groups blocking port 22.

Related errors


AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16). Data as JSON: /api/errors/db30e01a2e995f3e. Report an issue: GitHub.