{"record":{"id":"b32aabb0f78d946d","repo":"Hmbown/CodeWhale","slug":"saved-session-runtime-store-ownership-does-not-match","errorCode":null,"errorMessage":"Saved session Runtime store ownership does not match; refusing to recover another scope","messagePattern":"Saved session Runtime store ownership does not match; refusing to recover another scope","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/runtime_threads.rs","lineNumber":3255,"sourceCode":"        if !self.has_no_durable_work()? {\n            return Ok(false);\n        }\n        if self.has_scope_pinned_automation()? {\n            return Ok(false);\n        }\n        Ok(true)\n    }\n\n    pub(crate) fn validate_existing_store(&self) -> Result<()> {\n        anyhow::ensure!(\n            self.data_dir.is_absolute(),\n            \"Saved Runtime store path must be absolute\"\n        );\n        let root = checked_existing_runtime_store_dir(&self.data_dir)?;\n        let owner: RuntimeStoreOwner =\n            serde_json::from_str(&read_store_file(&root.join(AGENT_MAIL_OWNER_FILE))?)?;\n        validated_record_id(&owner.owner_id, \"Runtime owner id\")?;\n        anyhow::ensure!(\n            runtime_execution_scope(&owner.owner_id, &root.join(EVENT_TRANSACTION_LOCK_FILE))\n                == self.execution_scope,\n            \"Saved session Runtime store ownership does not match; refusing to recover another scope\"\n        );\n        Ok(())\n    }\n}\n\nfn runtime_execution_scope(owner_id: &str, event_lock_path: &Path) -> String {\n    let mut digest = Sha256::new();\n    digest.update(owner_id.as_bytes());\n    digest.update([0]);\n    digest.update(event_lock_path.as_os_str().as_encoded_bytes());\n    digest\n        .finalize()\n        .iter()\n        .map(|byte| format!(\"{byte:02x}\"))\n        .collect()","sourceCodeStart":3237,"sourceCodeEnd":3273,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/runtime_threads.rs#L3237-L3273","documentation":"validate_existing_store compares the ownership scope recorded in the store's owner file (AGENT_MAIL_OWNER_FILE) against the current execution scope. It throws 'Saved session Runtime store ownership does not match; refusing to recover another scope' when the store belongs to a different session/execution scope. This is a deliberate safety guard against cross-session contamination: one session must never adopt or mutate another session's runtime store.","triggerScenarios":"Opening a session with a binding whose data_dir contains an owner file whose runtime_execution_scope (owner_id + lock file) differs from the session's current execution_scope — e.g. resuming a copied or shared store directory under a different session id.","commonSituations":"Cloning or copying a session's runtime store directory to another machine/session; restoring a backup into a live store path; two TUI instances pointed at the same data_dir with different session ids; stale owner file after an unclean shutdown.","solutions":["Verify you are opening the store with the same session/execution scope that created it.","If the store was copied or restored, remove or fix AGENT_MAIL_OWNER_FILE so it matches the current scope — only if no other session owns it.","Point the new session at its own fresh data_dir instead of sharing the other scope's store.","Check for a stale EVENT_TRANSACTION_LOCK_FILE and a live owner process before touching the owner file."],"exampleFix":"// before: sharing one store across sessions\n--data-dir /shared/runtime-store  // owned by another scope\n// after: per-session store\n--data-dir /run/app/session-$SESSION_ID/store","handlingStrategy":"validation","validationCode":"// before resuming, check the owner file matches this session's scope\nlet owner: RuntimeStoreOwner =\n    serde_json::from_str(&std::fs::read_to_string(root.join(\"AGENT_MAIL_OWNER_FILE\"))?)?;\nanyhow::ensure!(\n    runtime_execution_scope(&owner.owner_id, &root.join(\"EVENT_TRANSACTION_LOCK_FILE\")) == my_scope,\n    \"store owned by another scope\"\n);\n","typeGuard":null,"tryCatchPattern":"match store.validate_existing_store() {\n    Err(e) if e.to_string().contains(\"ownership does not match\") => {\n        eprintln!(\"store belongs to another session; opening a fresh store instead\");\n        open_fresh_store()?;\n    }\n    r => r?,\n}\n","preventionTips":["Never copy or share a store directory between sessions or machines.","Give each session its own data_dir (per-session-id path).","Check for a live owner process before assuming an owner file is stale.","Restore backups into a new directory, not over a live store."],"tags":["session","ownership","validation","runtime-store"],"backgroundTag":"conflicting-config-options","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T21:17:16.096Z"}