astrid-runtime/astrid · error
unsafe workspace selection: {error}
Error message
unsafe workspace selection: {error} What it means
During kernel startup, `workspace_layout.resolve(&workspace_root)` rejected the workspace selection as unsafe (e.g. root/symlink/ownership problems per the layout rules). The kernel re-wraps the rejection with its original ErrorKind and the message prefix `unsafe workspace selection:` because it will only operate inside a safely-resolved project root.
Source
Thrown at crates/astrid-kernel/src/lib.rs:1065
runtime_key,
session_token,
token_path,
cli_socket_listener,
singleton_lock,
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
layout_origin,
} = resources;
#[cfg(not(unix))]
let _ = token_path;
home.clear_runtime_principal_scratch().map_err(|error| {
std::io::Error::other(format!(
"Failed to clear stale principal runtime scratch: {error}"
))
})?;
let workspace_selection = workspace_layout.resolve(&workspace_root).map_err(|error| {
std::io::Error::new(error.kind(), format!("unsafe workspace selection: {error}"))
})?;
let workspace_root = workspace_selection.project_root().to_path_buf();
let event_bus = Arc::new(EventBus::new());
let capsules = Arc::new(RwLock::new(CapsuleRegistry::new()));
// The canonical runtime has no native principal-home authority. Home
// and workspace mounts are bound from the durable storage provider;
// lifecycle compatibility callers receive an explicit `None` and
// must not recreate a host `principal_home` tree.
let home_root = None;
// Bootstrap the capability store (persistent) over the injected KV.
// Key rotation invalidates persisted tokens (fail-secure by design).
let capabilities = Arc::new(
CapabilityStore::with_kv_store(Arc::clone(&kv))
.await
.map_err(|e| {View on GitHub (pinned to affd8760f4)
Solutions
- Use the real, non-symlinked path as the workspace root (resolve the canonical path and cd there).
- Fix ownership/permissions so the workspace root belongs to the current user.
- Move the workspace to a location the layout rules permit.
- Read the inner `{error}` in the message — it names the specific layout rule that was violated.
Example fix
// before
let root = PathBuf::from("~/projects/link-to-app"); // symlink
// after
let root = std::fs::canonicalize("~/projects/link-to-app")?; // real path
let workspace = workspace_layout.resolve(&root)?; Defensive patterns
Strategy: try-catch
Validate before calling
let root = std::fs::canonicalize(&workspace_root)?;
if !root.is_dir() {
return Err("workspace root must be a real directory");
}
let selection = workspace_layout.resolve(&root)?; Type guard
fn safe_workspace_root(p: &std::path::Path) -> std::io::Result<bool> {
let real = std::fs::canonicalize(p)?;
Ok(real.is_dir() && real == p)
} Try / catch
match workspace_layout.resolve(&workspace_root) {
Err(e) => return Err(std::io::Error::new(e.kind(), format!("unsafe workspace selection: {e}; use a real, non-symlinked, user-owned directory"))),
Ok(sel) => sel,
}; Prevention
- Pass canonical (non-symlinked) workspace paths to the kernel.
- Ensure the workspace root is owned by the current user with sane permissions.
- Avoid running the tool from symlinked checkout or home paths in CI.
When it happens
Trigger: Starting the kernel with a workspace root that `workspace_layout.resolve` deems unsafe — symlinked or redirected workspace roots, disallowed locations, or ownership/permission mismatches on the path.
Common situations: Running the tool inside a symlinked project directory (or a symlinked HOME chain); a workspace mounted from another user's directory; CI checkouts with unusual symlink structures; containers mapping volumes with mismatched uids.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- leftover capsule authority receipt is not a regular file: {}
- legacy capsule authority root is not a regular directory: {}
- legacy capsule authority root contains a non-regular entry:
- legacy capsule authority root is not a regular directory: {}
- directory symlink {} not allowed in capsule source tree (ref
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/142a51edddf82a46.
Report an issue: GitHub.