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
- Inspect error.cause — it holds scp's trimmed stderr with the real reason
- Test connectivity first: `ssh user@host true`
- Fix or remove the offending ~/.ssh/config option if stderr mentions 'bad configuration option'
- 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
- Wait for the SSH port/health check before copying files to a fresh VM
- Keep ~/.ssh/config minimal on CI hosts — unsupported options break every scp
- Always read error.cause; the thrown message alone has no reason
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
- Failed to generate SSH key: ${privatePath} / ${publicPath}
- page-cache eviction failed for ${path}; results would be war
- not called
- Failed to install package "${module}"
- Invalid gzip data
AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16).
Data as JSON: /api/errors/db30e01a2e995f3e.
Report an issue: GitHub.