{"record":{"id":"41f3408eabe48343","repo":"astrid-runtime/astrid","slug":"keypair-name-already-exists-at-pass-for","errorCode":null,"errorMessage":"keypair {name:?} already exists at {} — pass --force to overwrite","messagePattern":"keypair (.+?) already exists at (.+?) — pass --force to overwrite","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/keypair.rs","lineNumber":221,"sourceCode":"\n// ── Command dispatch ─────────────────────────────────────────────\n\npub(crate) fn run(command: KeypairCommand) -> Result<ExitCode> {\n    match command {\n        KeypairCommand::Generate(args) => run_generate(args),\n        KeypairCommand::List(args) => run_list(&args),\n        KeypairCommand::Show(args) => run_show(&args),\n        KeypairCommand::Pubkey(args) => run_pubkey(&args),\n        KeypairCommand::Delete(args) => run_delete(&args),\n    }\n}\n\nfn run_generate(args: GenerateArgs) -> Result<ExitCode> {\n    let name = args.name.unwrap_or_else(default_name);\n    validate_name(&name)?;\n    let paths = KeyPaths::new(&name)?;\n    if paths.exists_any() && !args.force {\n        bail!(\n            \"keypair {name:?} already exists at {} — pass --force to overwrite\",\n            paths.private.display()\n        );\n    }\n\n    // Generate from the OS CSPRNG. ed25519-dalek's `Zeroizing` drop\n    // glue runs when `signing` falls out of scope, clearing the\n    // secret bytes from RAM.\n    let mut secret_bytes = [0u8; 32];\n    SysRng\n        .try_fill_bytes(&mut secret_bytes)\n        .context(\"OS CSPRNG unavailable while generating keypair\")?;\n    let signing = SigningKey::from_bytes(&secret_bytes);\n    secret_bytes = [0u8; 32]; // belt-and-suspenders; the SigningKey owns its own zeroizing copy\n    let _ = secret_bytes;\n\n    let verifying = signing.verifying_key();\n    let pub_hex = hex::encode(verifying.to_bytes());","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/keypair.rs#L203-L239","documentation":"`run_generate` refuses to overwrite an existing keypair. If any file for the named keypair (private key, public key, or meta) already exists on disk and --force was not passed, generation is aborted to prevent silent key loss.","triggerScenarios":"Running `astrid keypair generate <name>` when files for <name> already exist in the key directory and --force is absent; re-running a provisioning script twice without --force.","commonSituations":"Idempotent setup scripts re-executed; re-generating after a partial earlier run; accidental reuse of a name like 'default' or a hostname.","solutions":["Re-run with --force if overwriting is intentional (the old key will be replaced — back it up first).","Choose a different keypair name for the new key.","Inspect the path shown in the error to confirm whether the existing key is still needed before forcing.","Automate with an existence check before generate in scripts."],"exampleFix":"// before\nastrid keypair generate default\n// after\nastrid keypair generate default --force","handlingStrategy":"validation","validationCode":"astrid keypair list | grep -qx \"$NAME\" && FORCE=--force || FORCE=","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Make idempotent scripts pass --force deliberately or check existence first","Use unique keypair names per host/purpose","Back up keys before any forced regenerate"],"tags":["cli","file-conflict","keypair"],"backgroundTag":"file-already-exists","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}