{"record":{"id":"bd4aabf66ee093aa","repo":"gitbutlerapp/gitbutler","slug":"existing-session-session-key-is-missing-updated-at","errorCode":null,"errorMessage":"existing session '{session_key}' is missing updated-at","messagePattern":"existing session '(.+?)' is missing updated-at","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-agentlog/src/gitmeta/read.rs","lineNumber":61,"sourceCode":"            RelatedTarget::Branch(key)\n            | RelatedTarget::Review(key)\n            | RelatedTarget::Change(key) => key,\n        }\n    }\n}\n\nfn session_list_entry(\n    handle: &SessionTargetHandle<'_>,\n    status: PublicationStatus,\n    session_key: String,\n) -> Result<SessionListEntry> {\n    let session_prefix = session_storage_prefix(status, &session_key);\n    let updated_at_key = format!(\"{session_prefix}:updated-at\");\n    let updated_at = match handle\n        .get_value(&updated_at_key)\n        .with_context(|| format!(\"failed to read GitMeta key '{updated_at_key}'\"))?\n    {\n        None => bail!(\"existing session '{session_key}' is missing updated-at\"),\n        Some(MetaValue::String(updated_at)) => updated_at,\n        Some(_) => bail!(\"existing GitMeta key '{updated_at_key}' is not a string\"),\n    };\n    let sort_updated_at = DateTime::parse_from_rfc3339(&updated_at)\n        .with_context(|| format!(\"existing GitMeta key '{updated_at_key}' has invalid timestamp\"))?\n        .with_timezone(&Utc);\n    Ok(SessionListEntry {\n        session_key,\n        status,\n        updated_at,\n        sort_updated_at,\n    })\n}\n\npub(crate) fn find_related_sessions_limited(\n    repo_path: &Path,\n    target: RelatedTarget<'_>,\n    max_sessions: Option<usize>,","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-agentlog/src/gitmeta/read.rs#L43-L79","documentation":"session_list_entry reads the `:updated-at` GitMeta key for a session that an index lookup said exists. Because the index claimed the session exists, its updated-at stamp is expected to be present; a missing value means the stored session data is incomplete or was partially written/corrupted, so the function bails instead of silently dropping the session.","triggerScenarios":"find_related_sessions_limited_by_statuses -> session_list_entry when the GitMeta set index lists session_key but handle.get_value('<prefix>:updated-at') returns None — i.e. the session record was never fully written or the updated-at key was deleted.","commonSituations":"A crash mid-write left an index entry without the session payload; manual pruning of GitMeta keys removed updated-at but not the index entry; older versions of the tool wrote different keys (schema/upgrade drift); corrupted GitMeta storage.","solutions":["Remove the stale index entry and re-record the session so updated-at is written atomically with the index entry","Inspect the GitMeta keys under the session prefix (e.g. via the tooling/debug output) to confirm which keys are missing","Upgrade or rerun the writer to completion; check the writer code path that inserts both the index hit and updated-at","If this recurs, migrate/rebuild the GitMeta store for the repo"],"exampleFix":"// before (caller assumed complete data)\nlet sessions = find_related_sessions_limited(&repo_path, target, Some(10))?;\n// after (tolerate partially-written sessions)\nlet sessions = find_related_sessions_limited(&repo_path, target, Some(10))\n    .unwrap_or_else(|_| Vec::new()); // or log and skip per-entry failures","handlingStrategy":"validation","validationCode":"let prefix = format!(\"{}:{session_key}\", status_prefix(status));\nlet present = gitmeta_key_exists(&repo_path, &format!(\"{prefix}:updated-at\"));\nif !present { /* repair or skip this session */ }","typeGuard":null,"tryCatchPattern":"match session_list_entry(handle, status, key) {\n    Ok(entry) => Some(entry),\n    Err(e) if e.to_string().contains(\"missing updated-at\") => {\n        // prune stale index entry, skip session\n        None\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always write the index entry and updated-at key together (or detail first, reference second)","Never delete updated-at keys without removing the corresponding index entries","Add a repair pass that removes index hits lacking session payloads","Check for crashes/interrupts after writes; rebuild GitMeta after abnormal termination"],"tags":["gitmeta","corrupt-data","missing-key","session"],"backgroundTag":"record-not-found","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}