gitbutlerapp/gitbutler · error
existing GitMeta key '{transcript_key}' is missing
Error message
existing GitMeta key '{transcript_key}' is missing What it means
`read_transcript_entries` reads the session's raw transcript under `<session_prefix>:transcript` and requires it to exist as a `MetaValue::List` — unlike the preview path in `session_outline.rs`, absence is fatal here. The bail fires when a session is expected to have a transcript but the key is missing entirely. That points to an incomplete publish, an older data format, or a partially synced state.
Source
Thrown at crates/but-agentlog/src/gitmeta/read_support.rs:76
return Ok(None);
};
let MetaValue::String(detail) = value else {
bail!("existing GitMeta key '{detail_key}' is not a string");
};
serde_json::from_str(&detail)
.with_context(|| format!("existing GitMeta key '{detail_key}' has invalid JSON"))
.map(Some)
}
pub(super) fn read_transcript_entries(
handle: &SessionTargetHandle<'_>,
transcript_key: &str,
) -> Result<Vec<ListEntry>> {
let Some(transcript_value) = handle
.get_value(transcript_key)
.with_context(|| format!("failed to read GitMeta key '{transcript_key}'"))?
else {
bail!("existing GitMeta key '{transcript_key}' is missing");
};
let MetaValue::List(transcript_entries) = transcript_value else {
bail!("existing GitMeta key '{transcript_key}' is not a list");
};
Ok(transcript_entries)
}
pub(super) fn transcript_records_by_hash<T>(
entries: Vec<ListEntry>,
needed_hashes: &std::collections::HashSet<String>,
mut parse_record: impl FnMut(&str) -> Option<(String, T)>,
) -> HashMap<String, T> {
let mut records = HashMap::with_capacity(needed_hashes.len());
for entry in entries.into_iter().rev() {
let Some((record_hash, record)) = parse_record(&entry.value) else {
continue;
};
if !needed_hashes.contains(&record_hash) {View on GitHub (pinned to caf1f223d3)
Solutions
- Run `but agentlog sync` to complete the state and retry
- Re-capture the session via the hook (new agent activity re-stores `:transcript`) and re-publish
- If the original transcript file still exists locally (e.g. ~/.claude or ~/.codex session log), re-run capture from it
- If the transcript is gone for good, treat the session as summary-only: delete or skip its transcript-dependent records
Example fix
// before
let entries = read_transcript_entries(&handle, &transcript_key)?;
// after: check existence first and degrade gracefully
let entries = match handle.get_value(&transcript_key)? {
Some(MetaValue::List(entries)) => entries,
Some(_) => bail!("transcript key '{transcript_key}' has the wrong type"),
None => { eprintln!("session has no stored transcript; skipping"); Vec::new() }
}; Defensive patterns
Strategy: validation
Validate before calling
// Check transcript presence before record reassembly
let transcript_key = format!("{session_prefix}:transcript");
if handle.get_value(&transcript_key)?.is_none() {
eprintln!("no stored transcript for session; run sync or re-capture");
} Type guard
fn transcript_present(handle: &SessionTargetHandle<'_>, key: &str) -> Result<bool> {
Ok(handle.get_value(key)?.is_some())
} Try / catch
match read_transcript_entries(&handle, &transcript_key) {
Ok(entries) => entries,
Err(err) if err.to_string().contains("is missing") => Vec::new(),
Err(err) => return Err(err),
} Prevention
- Treat interrupted publishes as incomplete: re-run publish rather than reading
- Keep the original agent transcript files until sessions are confirmed synced
- Re-capture old sessions before relying on transcript-dependent views
When it happens
Trigger: Record-reassembly paths (`show`, record-hash lookups) on a session that has turns/summaries but no `:transcript` key — e.g. the session was published by a writer that did not store transcripts, or a pull/push cycle dropped it.
Common situations: Sessions captured before the transcript-storage feature; interrupted or conflicted GitMeta sync; a turn list rewritten without the matching transcript; deleting keys manually while debugging.
Related errors
- existing GitMeta key '{detail_key}' is missing
- existing GitMeta key '{transcript_key}' is not a list
- existing GitMeta key '{transcript_key}' is not a list
- existing GitMeta key '{updated_at_key}' is not a string
- existing GitMeta key '{index_key}' is not a set
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/202c5dee45570b4a.
Report an issue: GitHub.