tinyhumansai/openhuman · error

Failed to canonicalize workspace: {e}

Error message

Failed to canonicalize workspace: {e}

What it means

Before any read-modify-write, the tool canonicalizes the workspace root so the target path (workspace + allowed file) can be checked against symlink-based escapes. If std::fs::canonicalize fails — typically the workspace directory was deleted, moved, or is unreadable — this error aborts the operation as a security guard failure, not a content problem.

Source

Thrown at src/openhuman/tools/impl/filesystem/update_memory_md.rs:250

        let content = args
            .get("content")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'content' parameter"))?;

        // Guard: only allow MEMORY.md and SKILL.md.
        if !ALLOWED_FILES.contains(&file) {
            return Ok(ToolResult::error(format!(
                "File '{file}' is not allowed. Permitted files: MEMORY.md, SKILL.md"
            )));
        }

        let target_path = workspace_dir.join(file);

        // Prevent symlink-based workspace escape.
        let workspace_canon = self
            .workspace_dir_for_context(context)
            .canonicalize()
            .map_err(|e| anyhow::anyhow!("Failed to canonicalize workspace: {e}"))?;
        // Check parent dir exists and canonicalize to detect symlinks.
        let parent = target_path.parent().unwrap_or(&workspace_dir);
        let parent_canon = parent
            .canonicalize()
            .unwrap_or_else(|_| parent.to_path_buf());
        if !parent_canon.starts_with(&workspace_canon) {
            return Ok(ToolResult::error(format!(
                "File path '{file}' resolves outside workspace"
            )));
        }

        tracing::debug!("[update_memory_md] action={action} file={file} path={target_path:?}");

        // #4458: serialize the whole read-modify-write against concurrent runs
        // targeting the same workspace. The guard is held across read + atomic
        // write so no interleaving append can be lost.
        let lock = workspace_write_lock(&workspace_dir);
        let _guard = lock.lock().await;

View on GitHub (pinned to 7491200858)

Solutions

  1. Verify the workspace directory still exists and is readable/writable
  2. Recreate or re-resolve the workspace root, then retry the tool call
  3. If the workspace moved, restart the session so tools get the fresh path
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at src/openhuman/tools/impl/filesystem/update_memory_md.rs:250 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/f8157a5ac25a83e3. Report an issue: GitHub.