tinyhumansai/openhuman · error
[agent] replay list_active_runs failed: {e}
Error message
[agent] replay list_active_runs failed: {e} What it means
Active-run listing failed: one of list_by_thread / list_by_root / list_active on FileStatusStore errored (replay/ops.rs:154). The thread/root/active query selection happens before the store call, so the failure is in reading the kv status store itself — lock contention, missing or corrupt workspace store, permissions.
Source
Thrown at src/openhuman/agent/tinyagents/replay/ops.rs:154
pub(crate) async fn list_active_runs(
workspace: &Path,
thread_id: Option<&str>,
root_run_id: Option<&str>,
) -> anyhow::Result<Vec<HarnessRunStatus>> {
log::debug!(
"[agent] replay list_active_runs thread_id={:?} root_run_id={:?}",
thread_id,
root_run_id
);
let stores = open_session_stores(workspace);
let store = FileStatusStore::new(stores.kv);
let base = match (thread_id, root_run_id) {
(Some(thread), _) => store.list_by_thread(thread).await,
(None, Some(root)) => store.list_by_root(root).await,
(None, None) => store.list_active().await,
}
.map_err(|e| anyhow::anyhow!("[agent] replay list_active_runs failed: {e}"))?;
let mut runs: Vec<HarnessRunStatus> = base.into_iter().filter(is_active).collect();
// If a caller supplied BOTH a thread and a root, the thread query drove the
// base list; narrow it to the requested root as well.
if thread_id.is_some() {
if let Some(root) = root_run_id {
runs.retain(|s| s.root_run_id.as_str() == root);
}
}
log::debug!("[agent] replay list_active_runs returned={}", runs.len());
Ok(runs)
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;View on GitHub (pinned to a221052e0d)
Solutions
- Verify the workspace path is accessible and writable
- Retry the listing after the concurrent writer finishes — busy locks are transient
- If the status store is corrupted (crash mid-write), rebuild the workspace session stores
- Run listing queries from the process that owns the workspace
Defensive patterns
Strategy: retry
Validate before calling
if std::fs::metadata(workspace).is_err() {
anyhow::bail!("workspace missing at {} — cannot list runs", workspace.display());
} Try / catch
// Listing is poll-shaped: degrade gracefully instead of failing the caller
match list_active_runs(workspace, thread_id, root_run_id).await {
Ok(runs) => runs,
Err(e) if is_transient_store_error(&e) => Vec::new(), // retry next poll tick
Err(e) => return Err(e),
} Prevention
- Run listing polls from the workspace-owning process
- Distinguish transient (busy/lock) from permanent (missing/corrupt) store errors in handlers
- Avoid listing while restoring or copying a workspace directory
When it happens
Trigger: Listing active runs while another process holds the kv store lock; workspace directory moved or restored; corrupted status store; permission changes on the workspace tree.
Common situations: Dashboards/UI polling active runs against a busy core; resumed/recovered workspaces after a crash; shared workspaces across processes.
Related errors
- [agent] replay read_run_events_page failed run_id={run_id}:
- [agent] replay read_run_status failed run_id={run_id}: {e}
- artifact_list: {e}
- learning_save_profile: write failed: {e}
- Core rejected the meet_agent_list_calls request.
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/5c17c2af02c0e8d1.
Report an issue: GitHub.