nikivdev/code · error · anyhow::Error

ssh-keygen failed

Error message

ssh-keygen failed

What it means

setup generates an SSH keypair by invoking ssh-keygen and checking its exit status; a nonzero exit produces this terse error. Because stderr/stdout are inherited, the real reason (bad key type, weak passphrase policy, existing file with -N, no entropy) is printed directly to the terminal, but the returned error itself carries no detail.

Source

Thrown at src/ssh_keys.rs:89

    );
    let status = Command::new("ssh-keygen")
        .args([
            "-t",
            "ed25519",
            "-N",
            "",
            "-C",
            &comment,
            "-f",
            key_path.to_string_lossy().as_ref(),
        ])
        .stdin(Stdio::null())
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status()
        .context("failed to run ssh-keygen")?;
    if !status.success() {
        bail!("ssh-keygen failed");
    }

    let private_key = fs::read_to_string(&key_path)
        .with_context(|| format!("failed to read {}", key_path.display()))?;
    let public_key_path = key_path.with_extension("pub");
    let public_key = fs::read_to_string(&public_key_path)
        .with_context(|| format!("failed to read {}", public_key_path.display()))?;

    let identity = load_or_create_sealer_identity()?;
    let sealed = seal_private_key(private_key.as_bytes(), &identity)?;
    let (env_private_plain, env_public, env_fingerprint) = key_env_keys(&key_name);
    let (env_private_sealed, env_private_nonce, env_private_sealer_id) =
        key_env_sealed_keys(&key_name);

    env::set_personal_env_var(&env_private_sealed, &sealed.sealed_b64)?;
    env::set_personal_env_var(&env_private_nonce, &sealed.nonce_b64)?;
    env::set_personal_env_var(&env_private_sealer_id, &identity.sealer_id)?;
    env::set_personal_env_var(&env_public, public_key.trim())?;

View on GitHub (pinned to a747e741ae)

Solutions

  1. Read the ssh-keygen output printed above the error for the actual cause
  2. Delete or move the existing key files if setup is being re-run on the same path
  3. Check `ssh-keygen -t ed25519` works manually to confirm key-type support and version
  4. Pre-check key_path existence and skip generation if the keypair is already present

Example fix

// before: overwrites prompt fails with stdin null
.stdin(Stdio::null())
...
// after: skip generation when keys already exist
if !key_path.exists() {
    let status = Command::new("ssh-keygen")
        .args([...])
        .stdin(Stdio::null())
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status()
        .context("failed to run ssh-keygen")?;
    if !status.success() { bail!("ssh-keygen failed"); }
}
Defensive patterns

Strategy: validation

Validate before calling

// pre-checks before invoking ssh-keygen
if key_path.exists() {
    eprintln!("key already exists at {}, skipping generation", key_path.display());
} else {
    let out = std::process::Command::new("ssh-keygen")
        .arg("-t").arg("ed25519").arg("-l")
        .output()?;
    if !out.status.success() {
        eprintln!("ssh-keygen missing or lacks ed25519 support");
    }
}

Try / catch

match setup(&opts) {
    Ok(keys) => use_keys(keys),
    Err(e) if e.to_string() == "ssh-keygen failed" => {
        eprintln!("ssh-keygen exited nonzero — check the ssh-keygen output above for the real cause (existing file? unsupported key type?)");
        std::process::exit(1);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: `ssh-keygen` invoked by setup exits nonzero: key file already exists and ssh-keygen prompts/fails in non-interactive mode, unsupported key algorithm on an old ssh-keygen, missing ssh-keygen binary handling, or invalid comment/path characters.

Common situations: Re-running setup when the keypair already exists; minimal Docker images or Windows environments shipping an ssh-keygen that lacks the requested key type (e.g. ed25519 on ancient OpenSSH); ssh-keygen prompting for overwrite with stdin closed (Stdio::null) causing immediate failure.

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/8676898d3bf70444. Report an issue: GitHub.