xai-org/grok-build · error
failed to set mcp preferences permissions: {e}
Error message
failed to set mcp preferences permissions: {e} What it means
save_mcp_preferences_to writes JSON to a temp file then tightens permissions to 0o600 (owner read/write) before an atomic rename; if tokio::fs::set_permissions fails the error is wrapped with this message. Failure means the OS refused the chmod (permissions, ownership, or filesystem limitation).
Source
Thrown at crates/codegen/xai-grok-shell/src/util/config/mcp.rs:478
let json = serde_json::to_string_pretty(prefs)?;
if let Some(parent) = path.parent() {
tokio::fs::create_dir_all(parent).await?;
}
let tmp = path.with_extension(format!(
"json.tmp.{}{}",
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_nanos())
.unwrap_or(0)
));
tokio::fs::write(&tmp, &json).await?;
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
tokio::fs::set_permissions(&tmp, std::fs::Permissions::from_mode(0o600))
.await
.map_err(|e| anyhow::anyhow!("failed to set mcp preferences permissions: {e}"))?;
}
tokio::fs::rename(&tmp, path).await?;
Ok(())
}
/// Restore a single server key after a failed setup (best-effort).
pub(crate) async fn restore_mcp_preference_server(
server_name: &str,
previous: Option<McpServerPreferences>,
) -> Result<()> {
let load = load_mcp_preferences();
if !load.is_writable() {
return Ok(());
}
let mut prefs = load.file();
match previous {
Some(entry) => {
prefs.servers.insert(server_name.to_string(), entry);View on GitHub (pinned to bc7f02eddd)
Solutions
- Check ownership and permissions of the target directory (the process must own the temp file it just created).
- Point the temp path to a normal local filesystem (the file is created next to `path`, so ensure the config directory is writable and supports chmod).
- Inspect the chained io error ({e}) for the exact errno (EACCES, EPERM, EROFS) and fix accordingly.
- If 0o600 cannot be enforced, decide whether to fail closed (current behavior) or fall back to default permissions with a warning.
Example fix
// before
tokio::fs::set_permissions(&tmp, std::fs::Permissions::from_mode(0o600))
.await
.map_err(|e| anyhow!("failed to set mcp preferences permissions: {e}"))?;
// after — warn instead of aborting when chmod is unsupported
if let Err(e) = tokio::fs::set_permissions(&tmp, std::fs::Permissions::from_mode(0o600)).await {
tracing::warn!("could not tighten mcp preferences permissions: {e}");
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check the config dir supports chmod (unix)
#[cfg(unix)]
let ok = {
use std::os::unix::fs::PermissionsExt;
let probe = path.with_extension("perm-probe");
std::fs::write(&probe, b"")?;
let r = std::fs::set_permissions(&probe, std::fs::Permissions::from_mode(0o600)).is_ok();
let _ = std::fs::remove_file(&probe);
r
}; Try / catch
match save_mcp_preferences(&prefs).await {
Err(e) if e.to_string().contains("failed to set mcp preferences permissions") => {
log::warn!("chmod on config dir failed ({e}); writing with default perms");
save_without_strict_perms(&prefs).await
}
other => other,
} Prevention
- Keep config directories on local filesystems that support chmod
- Ensure the process user owns its config directory
- Don't point TMPDIR/config paths at exotic mounts (nfs, some overlays)
- Monitor for EROFS/EACCES when deploying in hardened containers
When it happens
Trigger: Calling save_mcp_preferences (or the round-trip test) when set_permissions on the temp file fails — e.g. temp dir on a filesystem that disallows chmod, or the process lacks ownership of the temp file.
Common situations: Saving MCP preferences on Windows non-unix builds (skipped), on network/overlay filesystems with restricted chmod, or when TMPDIR points to an unusual mount; disk-full/quota errors surfaced as permission problems.
Related errors
- hook write-deny ensure failed: {e}
- failed to open {}: {e}
- no .git file or directory found at {}
- unmount {}: {err}
- bind {}: {e}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/e584b062fa86638e.
Report an issue: GitHub.