Hmbown/CodeWhale · error
Runtime directory override conflicts with the saved…
Error message
Runtime directory override conflicts with the saved session's Runtime store
What it means
When constructing the runtime thread manager with a saved RuntimeStoreBinding, any runtime_dir_override() (e.g. from an environment variable or CLI flag) must resolve to exactly the store directory recorded in the binding. It throws 'Runtime directory override conflicts with the saved session's Runtime store' when the override's checked root differs from binding.data_dir, preventing the manager from silently reading/writing a different store than the session's.
Solutions
- Unset the runtime directory override (env var / flag) so the session's saved data_dir is used.
- Point the override at the exact directory recorded in the session binding (the path from the error context).
- Delete/regenerate the session binding if you intend to migrate to the override directory as its new store.
- Check checked_runtime_store_root's resolution of the override (symlinks/canonicalization can make paths that look equal differ).
Example fix
// before: override conflicts with saved session CODEWHALE_RUNTIME_DIR=/tmp/other-store app --resume session.json // after: match the saved store or drop the override unset CODEWHALE_RUNTIME_DIR && app --resume session.json
Defensive patterns
Strategy: validation
Validate before calling
// compare override and binding roots before constructing the manager
if let (Some(binding), Some(override_dir)) = (binding.as_ref(), runtime_dir_override()) {
anyhow::ensure!(
checked_runtime_store_root(override_dir)? == binding.data_dir,
"runtime dir override conflicts with saved session store"
);
}
Try / catch
match RuntimeThreadManager::new(manager_cfg, plugin_registry, binding.as_ref()).await {
Ok(m) => m,
Err(e) if e.to_string().contains("Runtime directory override conflicts") => {
eprintln!("dropping override to honor the saved session store");
RuntimeThreadManager::new(manager_cfg, plugin_registry, binding.as_ref()).await?
}
Err(e) => return Err(e),
}
Prevention
- Do not export runtime-dir overrides globally in shell profiles if you resume saved sessions.
- Canonicalize override paths (checked_runtime_store_root) so symlinks don't create false conflicts.
- Treat the session binding as authoritative: change the binding when migrating stores, not just the override.
- Document the runtime-dir env var in docs/ENVIRONMENTS.md so users know its effect.
When it happens
Trigger: Starting the manager with Some(binding) while a runtime directory override is set whose checked_runtime_store_root != binding.data_dir — e.g. CODEWHALE-style runtime dir env var pointing elsewhere while resuming a saved session.
Common situations: Developer has a runtime-dir env var exported globally but resumes an old session saved under a different directory; switching between dev/prod store directories while reusing a session file; running a second checkout whose default override differs from the session's store.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- Saved Runtime store path must be absolute
- Saved session Runtime store ownership does not match…
- 127
- A pinned task provider requires an explicit model
- agent profile reasoning_effort must be one of: inherit…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/1c358e71517a0224.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/runtime_threads.rs:5043
pub fn open_with_plugin_registry(
config: Config,
workspace: PathBuf,
manager_cfg: RuntimeThreadManagerConfig,
plugin_registry: Arc<crate::plugins::PluginRegistry>,
) -> Result<Self> {
Self::open_inner(config, workspace, manager_cfg, Some(plugin_registry), None)
}
pub(crate) fn open_for_session(
config: Config,
workspace: PathBuf,
mut manager_cfg: RuntimeThreadManagerConfig,
plugin_registry: Arc<crate::plugins::PluginRegistry>,
binding: Option<&RuntimeStoreBinding>,
) -> Result<Self> {
if let Some(binding) = binding {
if let Some(override_dir) = runtime_dir_override() {
anyhow::ensure!(
checked_runtime_store_root(override_dir)? == binding.data_dir,
"Runtime directory override conflicts with the saved session's Runtime store"
);
}
if binding.is_missing_session_store()? {
// Never claim the missing owner's scope. A fresh store cannot
// execute its queued tasks, approvals, mail or automations.
// All recovery attempts for this conversation contend on the
// same host lock. Random paths would let two processes mint
// competing owners before either saves the repaired binding.
manager_cfg.data_dir = manager_cfg
.data_dir
.with_file_name("runtime-recovered-session");
return Self::open_inner(
config,
workspace,
manager_cfg,
Some(plugin_registry),View on GitHub (pinned to 73e0f67d83)