Hmbown/CodeWhale · error

Runtime store root

Error message

Runtime store root

What it means

Panic from `event_lock_path.parent()` in `session_store_binding`. `Path::parent()` returns None only when the path is a bare filename or root with no parent; the code asserts the configured event lock path always lives under a store root directory.

Solutions

  1. Ensure `event_lock_path` is always an absolute path with a directory component
  2. Validate the configured lock path at config load time (fail loud per repo convention)
  3. Guard the call site with a check that returns a descriptive error instead of panicking

Example fix

// before
data_dir: self.store.event_lock_path.parent().expect("Runtime store root").to_path_buf(),
// after
data_dir: self
    .store
    .event_lock_path
    .parent()
    .expect("Runtime store root: event_lock_path must include a parent directory")
    .to_path_buf(),
Defensive patterns

Strategy: validation

Validate before calling

debug_assert!(self.store.event_lock_path.parent().is_some(), "event_lock_path must have a parent directory");

Type guard

fn has_parent(p: &Path) -> bool { p.parent().is_some() }

Try / catch

let root = self.store.event_lock_path.parent().ok_or_else(|| anyhow!("Runtime store root missing: {}", self.store.event_lock_path.display()))?;

Prevention

When it happens

Trigger: The Runtime store's `event_lock_path` being misconfigured to a relative bare filename (no directory component), leaving `parent()` with nothing to return when `session_store_binding` is called.

Common situations: Config files or defaults setting the lock path without its parent directory after a config migration or typo like `event.lock` instead of `/path/to/store/event.lock`.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/e00beed4c961a89e. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/runtime_threads.rs:5153

    pub fn attach_task_manager(&self, task_manager: crate::task_manager::SharedTaskManager) {
        *self.task_manager.lock() = Arc::downgrade(&task_manager);
    }

    /// Identity of the actual Runtime store, not a model-supplied session label.
    pub(crate) fn task_execution_identity(&self) -> (String, Arc<RuntimeProcessOwnerLock>) {
        (
            runtime_execution_scope(&self.store.owner_id, &self.store.event_lock_path),
            self._process_owner_lock.clone(),
        )
    }

    pub(crate) fn session_store_binding(&self) -> RuntimeStoreBinding {
        RuntimeStoreBinding {
            data_dir: self
                .store
                .event_lock_path
                .parent()
                .expect("Runtime store root")
                .to_path_buf(),
            execution_scope: self.task_execution_identity().0,
        }
    }

    pub(crate) async fn close_execution_admission(&self) {
        let _admission = self.config_admission.write().await;
        self.cancel_token.cancel();
        let _loading = self.engine_load.lock().await;
    }

    /// Close admission, then drain the existing engines and terminal receipt
    /// monitors. Ownership stays attached to this Runtime until its last user
    /// drops it, including any actual execution still awaiting shutdown.
    pub(crate) async fn shutdown_and_wait(&self) -> Result<()> {
        let _drain = self.shutdown_drain.lock().await;
        self.close_execution_admission().await;
        let (engines, active_turns) = {

View on GitHub (pinned to 73e0f67d83)