{"record":{"id":"1b5a6d639414be0e","repo":"GitoxideLabs/gitoxide","slug":"commit-at-rev-spec-is-not-signed","errorCode":null,"errorMessage":"Commit at {rev_spec} is not signed","messagePattern":"Commit at (.+?) is not signed","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"gitoxide-core/src/repository/commit.rs","lineNumber":25,"sourceCode":"use anyhow::{Context, Result, anyhow, bail};\nuse gix::{\n    bstr::{BStr, BString},\n    objs::commit::SIGNATURE_FIELD_NAME,\n};\n\n/// Note that this is a quick implementation of commit signature verification that ignores a lot of what\n/// git does and can do, while focussing on the gist of it.\n/// For this to go into `gix`, one will have to implement many more options and various validation programs.\npub fn verify(repo: gix::Repository, rev_spec: Option<&str>) -> Result<()> {\n    let rev_spec = rev_spec.unwrap_or(\"HEAD\");\n    let commit = repo\n        .rev_parse_single(format!(\"{rev_spec}^{{commit}}\").as_str())?\n        .object()?\n        .into_commit();\n    let outcome = commit\n        .verify_signature()\n        .context(\"Could not verify commit signature\")?\n        .ok_or_else(|| anyhow!(\"Commit at {rev_spec} is not signed\"))?;\n    std::io::stderr().write_all(&outcome.output)?;\n    if !outcome.is_valid() {\n        bail!(\"Commit at {rev_spec} has an invalid or untrusted signature\");\n    }\n    Ok(())\n}\n\n/// Note that this is a quick first prototype that lacks some of the features provided by `git verify-commit`.\npub fn sign(repo: gix::Repository, rev_spec: Option<&str>, mut out: impl std::io::Write) -> Result<()> {\n    let rev_spec = rev_spec.unwrap_or(\"HEAD\");\n    let object = repo\n        .rev_parse_single(format!(\"{rev_spec}^{{commit}}\").as_str())?\n        .object()?;\n    let mut commit_ref = object.to_commit_ref();\n    if commit_ref.extra_headers().pgp_signature().is_some() {\n        gix::trace::info!(\"The commit {id} is already signed, did nothing\", id = object.id);\n        writeln!(out, \"{id}\", id = object.id)?;\n        return Ok(());","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gitoxide-core/src/repository/commit.rs#L7-L43","documentation":"Thrown by `verify` in `gix repo commit verify` when `commit.verify_signature()` returns `None`, meaning the commit object carries no PGP/GPG signature at all. There is nothing to verify, so the command fails with this explicit message instead of reporting success.","triggerScenarios":"Running `gix repo commit verify <rev>` on a commit that was created without signing (no `gpgsig` header), e.g. `git commit` without `-S`.","commonSituations":"Verifying commits in repos where commit signing was never enabled (`commit.gpgsign=false`); testing unsigned history; CI checking signatures on repos with mixed signed/unsigned commits.","solutions":["Re-commit with signing: `git commit --amend -S` (or set `git config commit.gpgsign true`)","Only run verification against commits known to be signed; filter the revision list for signed commits first","If unsigned commits are acceptable, skip verify or treat this message as a no-op result in scripts"],"exampleFix":"// before\ngit commit -m \"work\"        # unsigned\ngix repo commit verify HEAD  # fails\n// after\ngit commit -S -m \"work\"      # signed\ngix repo commit verify HEAD","handlingStrategy":"validation","validationCode":"let commit = repo.rev_parse_single(format!(\"{rev}^{{commit}}\"))?.object()?.into_commit();\nlet signed = commit.decode()?.extra_headers().find(\"gpgsig\").is_some();\nif !signed {\n    return Err(\"commit is not signed; nothing to verify\".into());\n}","typeGuard":"fn is_signed(commit: &gix::objs::CommitRef) -> bool {\n    commit.extra_headers().find(\"gpgsig\").is_some()\n}","tryCatchPattern":"match verify_commit(rev) {\n    Err(e) if e.to_string().contains(\"is not signed\") => {\n        // record as unsigned, continue policy-appropriate handling\n    }\n    other => other?,\n}","preventionTips":["Enable `git config commit.gpgsign true` so all new commits are signed","When auditing, split revision lists into signed/unsigned before verification"],"tags":["commit","signature","gpg","verification","gitoxide"],"backgroundTag":"authentication-required","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"}