{"record":{"id":"f5032bb9b5ff81d7","repo":"gitbutlerapp/gitbutler","slug":"existing-gitmeta-key-transcript-key-is-not-a-l-f5032b","errorCode":null,"errorMessage":"existing GitMeta key '{transcript_key}' is not a list","messagePattern":"existing GitMeta key '(.+?)' is not a list","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-agentlog/src/gitmeta/session_outline.rs","lineNumber":90,"sourceCode":"\nfn session_previews(\n    handle: &SessionTargetHandle<'_>,\n    session_prefix: &str,\n    preview_hashes: &HashSet<String>,\n) -> Result<SessionPreviews> {\n    if preview_hashes.is_empty() {\n        return Ok(SessionPreviews::default());\n    }\n\n    let transcript_key = format!(\"{session_prefix}:transcript\");\n    let Some(value) = handle\n        .get_value(&transcript_key)\n        .with_context(|| format!(\"failed to read GitMeta key '{transcript_key}'\"))?\n    else {\n        return Ok(SessionPreviews::default());\n    };\n    let MetaValue::List(entries) = value else {\n        bail!(\"existing GitMeta key '{transcript_key}' is not a list\");\n    };\n\n    let mut previews = SessionPreviews::default();\n    let mut entries = entries;\n    entries.sort_by_key(|entry| entry.timestamp);\n    for entry in entries.into_iter().rev() {\n        if previews.latest_user.is_some() && previews.latest_assistant.is_some() {\n            break;\n        }\n\n        let Ok(record) = serde_json::from_str::<Value>(&entry.value) else {\n            continue;\n        };\n        let Some(record_hash) = record[\"record_hash\"].as_str() else {\n            continue;\n        };\n        if !preview_hashes.contains(record_hash) {\n            continue;","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-agentlog/src/gitmeta/session_outline.rs#L72-L108","documentation":"When building skim previews, `session_outline` reads the transcript key only if there are hashes to preview; a missing key returns empty previews, but a key that exists and is not a `MetaValue::List` bails. So this error means the `:transcript` value has the wrong shape while the preview path is trying to extract the latest user/assistant messages.","triggerScenarios":"`but agentlog skim` building session previews for a session whose `gitbutler:agent-session:<status>:<key>:transcript` key holds a String or Set variant instead of the List of timestamped entries.","commonSituations":"Version-skewed writers on the same GitMeta remote; conflicted merges of the metadata ref; manual edits to GitMeta keys; sessions restored from incompatible backups.","solutions":["Run `but agentlog sync` and retry skim","Re-capture and re-publish the affected session to rewrite the transcript key","Align `but` versions across machines","Restore the last List-valued version from GitMeta ref history or delete the malformed key (previews degrade to empty)"],"exampleFix":"// before\nlet MetaValue::List(entries) = value else { bail!(\"...\") };\n\n// after: fall back to empty previews when the shape is wrong\nlet entries = match value {\n    MetaValue::List(entries) => entries,\n    _ => return Ok(SessionPreviews::default()),\n};","handlingStrategy":"type-guard","validationCode":"// Before building previews, verify the transcript variant\nif let Some(value) = handle.get_value(&transcript_key)? {\n    if !matches!(value, MetaValue::List(_)) { /* fall back to empty previews */ }\n}","typeGuard":"fn previewable_transcript(v: Option<&MetaValue>) -> bool {\n    matches!(v, Some(MetaValue::List(_)))\n}","tryCatchPattern":"let entries = match handle.get_value(&transcript_key)? {\n    Some(MetaValue::List(entries)) => entries,\n    _ => return Ok(SessionPreviews::default()),\n};","preventionTips":["Run skim after sync when metadata was written elsewhere","Align but versions to keep transcript encoding uniform","Re-publish sessions showing empty previews to refresh their transcript keys"],"tags":["gitmeta","type-mismatch","transcript","skim","previews","rust"],"backgroundTag":"stored-data-type-mismatch","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}