gitbutlerapp/gitbutler · error
No trailers found on snapshot commit message
Error message
No trailers found on snapshot commit message
What it means
The FromStr impl for a snapshot commit parses the message into title, body, and a final trailer block. If the message has no section after the last empty-line split — i.e. no trailers — split.pop() yields None and this error is thrown. Snapshot commits are expected to always carry trailers (oplog metadata).
Solutions
- Use only oplog snapshot commits that were created by the tool (trailers intact).
- If trailers were lost, the commit cannot be interpreted as a snapshot — recreate the snapshot operation.
- Guard parsing: check the message for a trailer section (e.g. contains a known trailer key) before calling from_str.
- Check for older-format snapshots and migrate them instead of parsing directly.
Example fix
// before
let entry = OplogEntry::from_str(&message)?; // panics/errors without trailers
// after
if !message.contains("gitbutler:") {
return Err(anyhow!("not a snapshot commit"));
}
let entry = OplogEntry::from_str(&message)?; Defensive patterns
Strategy: validation
Validate before calling
fn has_trailers(msg: &str) -> bool {
msg.lines().rev().skip_while(|l| l.is_empty()).any(|l| l.contains(": ")) && msg.lines().count() >= 2
}
// call from_str only if has_trailers(message) Prevention
- Never amend or rewrite oplog snapshot commits.
- Validate commit messages contain the expected trailer keys before parsing.
- Handle legacy snapshots from older versions via a migration path.
When it happens
Trigger: Parsing a snapshot commit message that lacks a trailing trailer block — e.g. a hand-written or git-butchered commit message, or a snapshot created by a version that did not append trailers.
Common situations: Amended or rebased snapshot commits that lost trailers; manually editing oplog commits; restoring/parsing oplog entries from older repo states.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- cannot snapshot a null target commit id
- Commit is not a snapshot
- commit prefix ' ' is ambiguous
- commit ' ' is not part of the editable divergence
- Could not find range from
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/ab0e0f6f69848bdf.
Report an issue: GitHub.
Appendix: source
Thrown at crates/gitbutler-oplog/src/entry.rs:78
self
}
pub fn with_trailers(mut self, trailers: impl IntoIterator<Item = Trailer>) -> Self {
self.trailers.extend(trailers);
self
}
}
impl FromStr for SnapshotDetails {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let message_lines: Vec<&str> = s.lines().collect();
let mut split: Vec<&[&str]> = message_lines.split(|line| line.is_empty()).collect();
let title = split.remove(0).join("\n");
let mut trailers: Vec<Trailer> = split
.pop()
.ok_or(anyhow!("No trailers found on snapshot commit message"))?
.iter()
.filter_map(|s| Trailer::from_str(s).ok())
.collect();
let body = split.iter().map(|v| v.join("\n")).join("\n\n");
let body = if body.is_empty() { None } else { Some(body) };
let version = trailers
.iter()
.find_map(|t| match t {
Trailer::Version(version) => Some(*version),
_ => None,
})
.context("No version found on snapshot commit message")?;
let operation = trailers
.iter()
.find_map(|t| match t {
Trailer::Operation(operation_kind) => Some(*operation_kind),View on GitHub (pinned to 58e5313667)