tinyhumansai/openhuman · error
Failed to atomically persist active user state {}: {error}
Error message
Failed to atomically persist active user state {}: {error} What it means
The active-user marker is written atomically: create a temp file, write the TOML, `sync_all` (fsync), rename over the target path, then fsync the directory. This bail fires when the rename step fails — the temp file is removed, so no partial state is left; the previously active user marker (if any) remains in effect.
Source
Thrown at src/openhuman/config/schema/load_user_state.rs:189
.write(true)
.open(&temp_path)
.with_context(|| {
format!(
"Failed to create temporary active user state: {}",
temp_path.display()
)
})?;
temp_file
.write_all(toml_str.as_bytes())
.context("Failed to write temporary active user state")?;
temp_file
.sync_all()
.context("Failed to fsync temporary active user state")?;
drop(temp_file);
if let Err(error) = std::fs::rename(&temp_path, &path) {
let _ = std::fs::remove_file(&temp_path);
anyhow::bail!(
"Failed to atomically persist active user state {}: {error}",
path.display()
);
}
sync_directory(default_openhuman_dir)?;
tracing::debug!(user_id = %user_id, path = %path.display(), "active user written");
Ok(())
}
/// Removes the active user marker. After this, the next config load will
/// use the default (unauthenticated) openhuman directory.
pub fn clear_active_user(default_openhuman_dir: &Path) -> Result<()> {
let path = active_user_marker_path(default_openhuman_dir);
if path.exists() {
std::fs::remove_file(&path)
.with_context(|| format!("Failed to remove active user state: {}", path.display()))?;
tracing::debug!(path = %path.display(), "active user cleared");View on GitHub (pinned to 7491200858)
Solutions
- Retry the login/account switch — the write is idempotent (temp+rename) and transient locks usually clear.
- Fix permissions on the OpenHuman dir and ensure the marker path is a file; close/stop whatever holds it open.
- If persistent, remove the stale marker file and retry — the next config load falls back to the default unauthenticated openhuman directory, and a fresh marker can then be written.
Defensive patterns
Strategy: retry
Validate before calling
// Probe rename support in the OpenHuman dir before account switching
let dir = default_openhuman_dir();
let a = dir.join(format!(".probe-{}a", uuid::Uuid::new_v4()));
let b = dir.join(format!(".probe-{}b", uuid::Uuid::new_v4()));
std::fs::write(&a, b"")?;
std::fs::rename(&a, &b)?;
let _ = std::fs::remove_file(&b); Try / catch
for attempt in 0..3 {
match write_active_user_state(&user_id, &state).await {
Ok(()) => break,
Err(e) if e.to_string().contains("atomically persist active user state") && attempt < 2 => {
tokio::time::sleep(std::time::Duration::from_millis(250)).await; // transient lock
}
Err(e) => return Err(e),
}
} Prevention
- Exclude the OpenHuman dir from antivirus scanning on Windows
- Ensure the marker path is a file with writable parent
- Retry account switches after transient locks clear — the write is idempotent
When it happens
Trigger: Rename failures in the OpenHuman dir: permission restrictions, the marker path held open or locked (Windows sharing violation, antivirus), a read-only home directory, or the target path existing as a directory.
Common situations: Login/account-switch flows on Windows with AV or indexer locks; restricted home dirs in managed environments; concurrent login/account-switch writes.
Related errors
- Failed to atomically persist active workspace marker {}: {er
- Failed to atomically replace config file: {e}
- 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/e2cd29dd1bd73cab.
Report an issue: GitHub.