{"record":{"id":"79a50fe2b5e9ef27","repo":"gitbutlerapp/gitbutler","slug":"existing-gitmeta-key-turns-key-is-not-a-list","errorCode":null,"errorMessage":"existing GitMeta key '{turns_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/read_support.rs","lineNumber":29,"sourceCode":") -> Result<T> {\n    let gitmeta = Session::open(repo_path).context(\"failed to open GitMeta session\")?;\n    let project = Target::project();\n    let handle = gitmeta.target(&project);\n    read(&handle)\n}\n\npub(super) fn read_turn_summaries(\n    handle: &SessionTargetHandle<'_>,\n    turns_key: &str,\n) -> Result<Vec<StoredTurnSummary>> {\n    let Some(turns_value) = handle\n        .get_value(turns_key)\n        .with_context(|| format!(\"failed to read GitMeta key '{turns_key}'\"))?\n    else {\n        return Ok(Vec::new());\n    };\n    let MetaValue::List(turn_entries) = turns_value else {\n        bail!(\"existing GitMeta key '{turns_key}' is not a list\");\n    };\n\n    let summaries = stored_turn_summary_entries(turn_entries, turns_key)?\n        .into_iter()\n        .map(|entry| entry.summary)\n        .collect::<Vec<_>>();\n\n    Ok(summaries)\n}\n\npub(super) fn read_turn_detail(\n    handle: &SessionTargetHandle<'_>,\n    detail_key: &str,\n) -> Result<StoredTurnDetail> {\n    let Some(detail) = read_optional_turn_detail(handle, detail_key)? else {\n        bail!(\"existing GitMeta key '{detail_key}' is missing\");\n    };\n    Ok(detail)","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-agentlog/src/gitmeta/read_support.rs#L11-L47","documentation":"A session's turns are stored under `<session_prefix>:turns` as a `MetaValue::List` of summary entries. `read_turn_summaries` bails with this message when the key exists but is a String or Set instead of a List. Note the read path tolerates a missing key (returns empty) — only the wrong variant is fatal.","triggerScenarios":"`but agentlog show <session>` (and outline builders) reading the `:turns` key of a session whose turns were stored in a non-List variant — typically after version-skewed writes or corrupted metadata.","commonSituations":"Two agents on different `but` versions writing the same session; GitMeta push-conflict resolutions that mangled the turns entry; sessions created by a much older format that stored turns differently; manual key edits.","solutions":["Run `but agentlog sync` and retry the show command","Re-run the capture hook for that session (new agent activity rewrites `:turns`) or re-publish the session","Align `but` versions on every machine sharing the GitMeta remote","Inspect the GitMeta ref history for `gitbutler:agent-session:*:turns` and restore or delete the malformed entry"],"exampleFix":"// before\nlet turns = read_turn_summaries(&handle, &turns_key)?;\n\n// after: degrade a malformed turns list to empty\nlet turns = match read_turn_summaries(&handle, &turns_key) {\n    Ok(t) => t,\n    Err(err) if err.to_string().contains(\"is not a list\") => Vec::new(),\n    Err(err) => return Err(err),\n};","handlingStrategy":"type-guard","validationCode":"// Before show, confirm the turns key is a List\nif let Some(value) = handle.get_value(&format!(\"{session_prefix}:turns\"))? {\n    if !matches!(value, MetaValue::List(_)) {\n        eprintln!(\"session turns malformed; run `but agentlog sync`\");\n    }\n}","typeGuard":"fn turns_is_list(v: Option<&MetaValue>) -> bool {\n    matches!(v, Some(MetaValue::List(_)))\n}","tryCatchPattern":"match read_turn_summaries(&handle, &turns_key) {\n    Ok(t) => t,\n    Err(err) if err.to_string().contains(\"is not a list\") => Vec::new(),\n    Err(err) => return Err(err),\n}","preventionTips":["Let the capture hook finish writing before reading a session (avoid racing hook completion)","Sync before show when switching machines","Align but versions across writers of the same session"],"tags":["gitmeta","type-mismatch","turns","show","rust"],"backgroundTag":"stored-data-type-mismatch","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}