{"record":{"id":"9410fd5ac908de4c","repo":"GitoxideLabs/gitoxide","slug":"command-cmd-failed","errorCode":null,"errorMessage":"Command {cmd:?} failed","messagePattern":"Command (.+?) failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gitoxide-core/src/repository/commit.rs","lineNumber":62,"sourceCode":"    }\n\n    let mut cmd: std::process::Command = gix::command::prepare(\"gpg\").into();\n    cmd.args([\n        \"--keyid-format=long\",\n        \"--status-fd=2\",\n        \"--detach-sign\",\n        \"--sign\",\n        \"--armor\",\n    ])\n    .stdin(Stdio::piped())\n    .stdout(Stdio::piped());\n\n    gix::trace::debug!(\"About to execute {cmd:?}\");\n    let mut child = cmd.spawn()?;\n    child.stdin.take().expect(\"to be present\").write_all(&object.data)?;\n\n    if !child.wait()?.success() {\n        bail!(\"Command {cmd:?} failed\");\n    }\n\n    let mut signed_data = Vec::new();\n    child.stdout.expect(\"to be present\").read_to_end(&mut signed_data)?;\n\n    commit_ref\n        .extra_headers\n        .push((BStr::new(SIGNATURE_FIELD_NAME), Cow::Owned(BString::new(signed_data))));\n\n    let signed_id = repo.write_object(&commit_ref)?;\n    writeln!(&mut out, \"{signed_id}\")?;\n\n    Ok(())\n}\n\npub fn describe(\n    mut repo: gix::Repository,\n    rev_spec: Option<&str>,","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gitoxide-core/src/repository/commit.rs#L44-L80","documentation":"`sign` pipes the object data into an external signing command's stdin and expects a zero exit status. If the spawned command exits non-zero the function bails. The signing binary failed — bad key, wrong passphrase, missing config — and its stderr is typically inherited/visible.","triggerScenarios":"Calling `sign` with `commit.gpgsign`/`user.signingkey` pointing at a missing key, a gpg agent that can't prompt for a passphrase, or any custom `cmd` binary that exits non-zero.","commonSituations":"Non-interactive CI where gpg can't prompt for the passphrase; misconfigured `user.signingkey`; unsigned-key selection errors; the signing program not installed.","solutions":["Check the signing command's stderr output for the root cause","Pre-test the command manually (e.g. `echo test | gpg --clearsign`) and unlock the agent","Set `user.signingkey` / `gpg.program` correctly in git config","In CI, provide the key non-interactively (GPG passphrase via loopback pinentry)"],"exampleFix":"// before\nsign(repo, None, &mut out)?;\n// after\nstd::env::set_var(\"GPG_TTY\", \"\"); // let gpg prompt, or configure loopback pinentry in CI\nsign(repo, None, &mut out)?;","handlingStrategy":"try-catch","validationCode":"// verify the signing command works before signing\nlet probe = std::process::Command::new(\"gpg\").arg(\"--version\").output()?;\nif !probe.status.success() { anyhow::bail!(\"gpg unavailable\"); }","typeGuard":null,"tryCatchPattern":"if let Err(e) = sign(repo, None, &mut out) {\n    eprintln!(\"signing command failed: {e}; check gpg agent/passphrase\");\n}","preventionTips":["Configure `user.signingkey` and `gpg.program` explicitly","Unlock the gpg agent before batch signing","Set up loopback pinentry for headless environments"],"tags":["git","gpg","signing","external-command"],"backgroundTag":"git-command-failed","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}