Hmbown/CodeWhale · error

Saved Runtime store path must be absolute

Error message

Saved Runtime store path must be absolute

What it means

validate_existing_store ensures the saved runtime store's data_dir is an absolute path before opening it. It throws 'Saved Runtime store path must be absolute' when the persisted store binding contains a relative path, because the store owner/scope checks require a stable, resolvable filesystem location.

Solutions

  1. Fix the saved store path to an absolute path (canonicalize with realpath on the directory).
  2. If the store was genuinely relocated, update the session binding to the new absolute location.
  3. Delete the stale session binding and start a fresh session with an absolute data_dir.
  4. Upgrade to a version that stores absolute paths, then regenerate the session state.

Example fix

// before: relative path persisted
"data_dir": "runtime-store"
// after: absolute path persisted
"data_dir": "/home/user/.cache/app/runtime-store"
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_absolute_store_path(data_dir: &Path) -> Result<()> {
    anyhow::ensure!(data_dir.is_absolute(), "store path must be absolute: {}", data_dir.display());
    Ok(())
}

Type guard

fn is_absolute_dir(p: &Path) -> bool { p.is_absolute() }

Try / catch

match store.validate_existing_store() {
    Ok(()) => (),
    Err(e) if e.to_string().contains("must be absolute") => {
        let fixed = std::fs::canonicalize(&relative_dir)?;
        reopen_with_data_dir(fixed)?;
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Resuming a session whose saved RuntimeStoreBinding / data_dir was persisted as a relative path (e.g. saved from a different working directory, or hand-edited state file), then calling validate_existing_store().

Common situations: Session state file written by an older version that stored relative paths; user moved/edited the session store file; running the binary from a different cwd with a relative --runtime-dir style value persisted.

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/6114db42d02adf9a. Report an issue: GitHub.

Appendix: source

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

            return Ok(false);
        }
        if !self.data_dir.is_dir() {
            return Ok(false);
        }
        if self.has_live_holder()? {
            return Ok(false);
        }
        if !self.has_no_durable_work()? {
            return Ok(false);
        }
        if self.has_scope_pinned_automation()? {
            return Ok(false);
        }
        Ok(true)
    }

    pub(crate) fn validate_existing_store(&self) -> Result<()> {
        anyhow::ensure!(
            self.data_dir.is_absolute(),
            "Saved Runtime store path must be absolute"
        );
        let root = checked_existing_runtime_store_dir(&self.data_dir)?;
        let owner: RuntimeStoreOwner =
            serde_json::from_str(&read_store_file(&root.join(AGENT_MAIL_OWNER_FILE))?)?;
        validated_record_id(&owner.owner_id, "Runtime owner id")?;
        anyhow::ensure!(
            runtime_execution_scope(&owner.owner_id, &root.join(EVENT_TRANSACTION_LOCK_FILE))
                == self.execution_scope,
            "Saved session Runtime store ownership does not match; refusing to recover another scope"
        );
        Ok(())
    }
}

fn runtime_execution_scope(owner_id: &str, event_lock_path: &Path) -> String {
    let mut digest = Sha256::new();

View on GitHub (pinned to 73e0f67d83)