nikivdev/code · error
SSH mode is forced but no key is available. Run `f ssh setup
Error message
SSH mode is forced but no key is available. Run `f ssh setup` or `f ssh unlock` (error: {}) What it means
clone_git_like enforces SSH policy before cloning: if ssh_mode() reports Force but no SSH identities exist, it attempts to generate/ensure a default key; if that also fails, it bails with this message including the underlying error. It tells the user exactly which commands restore an available key.
Source
Thrown at src/repos.rs:70
Some(ReposAction::HomeBranchStatus(opts)) => run_home_branch_status(opts),
Some(ReposAction::BootstrapHomeBranch(opts)) => run_bootstrap_home_branch(opts),
Some(ReposAction::MigrateHomeBranch(opts)) => run_migrate_home_branch(opts),
Some(ReposAction::Create(opts)) => publish::run_github(opts),
Some(ReposAction::Capsule(opts)) => repo_capsule::run_capsule(opts),
Some(ReposAction::Alias(cmd)) => repo_capsule::run_alias(cmd),
None => fuzzy_select_repo(),
}
}
/// Clone into the current working directory (git clone style destination behavior).
pub fn clone_git_like(opts: CloneOpts) -> Result<()> {
ssh::ensure_ssh_env();
let mode = ssh::ssh_mode();
if matches!(mode, ssh::SshMode::Force) && !ssh::has_identities() {
match ssh_keys::ensure_default_identity(24) {
Ok(()) => {}
Err(err) => {
bail!(
"SSH mode is forced but no key is available. Run `f ssh setup` or `f ssh unlock` (error: {})",
err
);
}
}
}
let clone_url = resolve_git_like_clone_url(&opts.url)?;
let mut cmd = Command::new("git");
cmd.arg("clone").arg(&clone_url);
if let Some(dir) = opts.directory {
cmd.arg(dir);
}
let status = cmd
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())View on GitHub (pinned to a747e741ae)
Solutions
- Run `f ssh setup` to create/configure a default SSH key
- Run `f ssh unlock` if you have an existing encrypted key that needs unlocking
- Verify `ssh-add -l` shows a key; start the agent (`eval "$(ssh-agent)"`) and add the key
- Test with `ssh -T git@github.com` to confirm SSH works before cloning
Example fix
// before f clone git@github.com:org/repo.git // fails: forced SSH, no key // after f ssh setup f clone git@github.com:org/repo.git
Defensive patterns
Strategy: validation
Validate before calling
const { execSync } = require("child_process");
function hasSshIdentity() {
try { return execSync("ssh-add -l", { stdio: ["ignore", "pipe", "ignore"] }).toString().trim().length > 0; }
catch { return false; }
}
if (!hasSshIdentity()) throw new Error("no SSH identity; run `f ssh setup` before cloning"); Try / catch
try {
run(["f", "clone", url]);
} catch (e) {
if (String(e).includes("SSH mode is forced but no key")) {
console.error("Run `f ssh setup` or `f ssh unlock`, then retry the clone.");
} else throw e;
} Prevention
- Run `f ssh setup` once on every new machine before using forced SSH mode
- Keep ssh-agent running and keys loaded after reboots (`ssh-add`)
- Check `ssh-add -l` shows a key before scripted clone operations
When it happens
Trigger: `f` clone with SSH mode forced while `ssh::has_identities()` is false AND ssh_keys::ensure_default_identity(24) returns Err (e.g. ssh-agent unavailable, keychain unlock failure, permission error writing the key).
Common situations: Fresh machine with no SSH key set up; agent not running / key not loaded after reboot; encrypted key that was never unlocked; forced SSH config pointing at Git remotes on a machine without keys.
Related errors
- git clone failed
- jj git export retry loop should always return
- Lin.app is not running
- No branches available to search
- No branches matched query '{}'.
AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01).
Data as JSON: /api/errors/2c112afd2009e58a.
Report an issue: GitHub.