tinyhumansai/openhuman · error
Failed to atomically persist active workspace marker {}: {er
Error message
Failed to atomically persist active workspace marker {}: {error} What it means
The active-workspace marker is persisted atomically: serialize state, write to a UUID-suffixed temp file in the default config dir, then `fs::rename` over the marker path (followed by a directory fsync). This bail fires when the rename step fails — the temp file is removed first, so no half-written marker is left; the previous marker, if any, remains authoritative.
Source
Thrown at src/openhuman/config/schema/load/dirs.rs:233
config_dir: config_dir.to_string_lossy().into_owned(),
};
let serialized =
toml::to_string_pretty(&state).context("Failed to serialize active workspace marker")?;
let temp_path = default_config_dir.join(format!(
".{ACTIVE_WORKSPACE_STATE_FILE}.tmp-{}",
uuid::Uuid::new_v4()
));
fs::write(&temp_path, serialized).await.with_context(|| {
format!(
"Failed to write temporary active workspace marker: {}",
temp_path.display()
)
})?;
if let Err(error) = fs::rename(&temp_path, &state_path).await {
let _ = fs::remove_file(&temp_path).await;
anyhow::bail!(
"Failed to atomically persist active workspace marker {}: {error}",
state_path.display()
);
}
super::sync_directory(&default_config_dir).await?;
Ok(())
}
pub(crate) fn resolve_config_dir_for_workspace(workspace_dir: &Path) -> (PathBuf, PathBuf) {
let workspace_config_dir = workspace_dir.to_path_buf();
if workspace_config_dir.join("config.toml").exists() {
return (
workspace_config_dir.clone(),
workspace_config_dir.join("workspace"),
);
}
View on GitHub (pinned to 7491200858)
Solutions
- Retry the workspace switch — the write is idempotent (temp+rename) and transient locks usually clear.
- Check permissions on `~/.openhuman`, ensure the marker path is a file not a directory, and close/stop processes holding it open.
- On Windows, exclude the `.openhuman` directory from real-time antivirus scanning or retry after the scan completes.
Defensive patterns
Strategy: retry
Validate before calling
// Probe that the config dir supports write+rename before switching workspaces
let dir = default_config_dir();
let a = dir.join(format!(".probe-{}a", uuid::Uuid::new_v4()));
let b = dir.join(format!(".probe-{}b", uuid::Uuid::new_v4()));
tokio::fs::write(&a, b"").await?;
tokio::fs::rename(&a, &b).await?;
let _ = tokio::fs::remove_file(&b).await; Try / catch
for attempt in 0..3 {
match persist_active_workspace_marker(&state).await {
Ok(()) => break,
Err(e) if e.to_string().contains("atomically persist active workspace marker") && attempt < 2 => {
tokio::time::sleep(std::time::Duration::from_millis(250)).await; // transient lock — retry
}
Err(e) => return Err(e),
}
} Prevention
- Exclude ~/.openhuman from antivirus and indexer scanning on Windows
- Ensure the config dir is writable and the marker stays on one filesystem
- Do not hold workspace marker files open in external tools while switching workspaces
When it happens
Trigger: Rename failures in the config dir: the target held open/locked (Windows sharing violation, antivirus, indexer), `~/.openhuman` read-only or ACL-restricted, the marker path itself being a directory, or temp and target ending up on different filesystems.
Common situations: Windows machines with antivirus or search indexer briefly locking the marker; permission-restricted home dirs in managed environments; two processes switching workspaces at the same instant.
Related errors
- Failed to atomically replace config file: {e}
- Failed to atomically persist active user state {}: {error}
- Working directory '{}' is not a directory. Set a valid path
- Config path is a directory, not a file: {}
- OPENAI_CODEX_OAUTH_MISSING_AUTH_URL
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/0cf11bcfd6196a7d.
Report an issue: GitHub.