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
- Read the ssh-keygen output printed above the error for the actual cause
- Delete or move the existing key files if setup is being re-run on the same path
- Check `ssh-keygen -t ed25519` works manually to confirm key-type support and version
- 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
- Skip key generation when the keypair already exists to stay idempotent
- Verify ssh-keygen supports the requested key type (ed25519) on the target platform
- Never pipe Stdio::null to stdin if ssh-keygen might prompt (e.g. overwrite)
- Test `ssh-keygen -t ed25519` manually in fresh containers before automating it
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
- ssh-agent failed: {}
- editor exited with status {}
- suggested command exited unsuccessfully with status {}
- {} exited with {}
- failed to read from codex: {}
AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01).
Data as JSON: /api/errors/8676898d3bf70444.
Report an issue: GitHub.