tinyhumansai/openhuman · error

learning_save_profile: {e}

Error message

learning_save_profile: {e}

What it means

Thrown by learning_save_profile when config_rpc::load_config_with_timeout() fails before the markdown can be written. That helper loads the TOML Config (with env overrides) under a bounded deadline inside the process; failure means the config file was unreadable/invalid or the load exceeded its timeout (Display-only {e}, no error chain). Without a Config the tool cannot resolve workspace_dir for PROFILE.md.

Source

Thrown at src/openhuman/agent/learning/tools.rs:530

            },
            "required": ["markdown"]
        })
    }

    fn permission_level(&self) -> PermissionLevel {
        PermissionLevel::Write
    }

    async fn execute(&self, args: serde_json::Value) -> anyhow::Result<ToolResult> {
        log::debug!("[tool][learning] save_profile invoked");
        let markdown = read_required_str(&args, "markdown")?;
        let summarize = args
            .get("summarize")
            .and_then(serde_json::Value::as_bool)
            .unwrap_or(false);
        let config = config_rpc::load_config_with_timeout()
            .await
            .map_err(|e| anyhow::anyhow!("learning_save_profile: {e}"))?;
        let body = if summarize {
            crate::openhuman::agent::learning::linkedin_enrichment::summarise_profile_with_llm(
                &config, &markdown,
            )
            .await
            .map_err(|e| anyhow::anyhow!("learning_save_profile: summarisation failed: {e:#}"))?
        } else {
            markdown
        };
        let path = config.workspace_dir.join("PROFILE.md");
        if let Some(parent) = path.parent() {
            tokio::fs::create_dir_all(parent)
                .await
                .map_err(|e| anyhow::anyhow!("learning_save_profile: create dir failed: {e}"))?;
        }
        tokio::fs::write(&path, &body)
            .await
            .map_err(|e| anyhow::anyhow!("learning_save_profile: write failed: {e}"))?;

View on GitHub (pinned to a221052e0d)

Solutions

  1. Validate config.toml parses (openhuman config RPC get, or re-run the core) and fix reported syntax/type errors
  2. Retry once filesystem contention clears — the timeout variant fails transiently under lock pressure
  3. Confirm the workspace directory exists and the user has write access
  4. Check OPENHUMAN_* env overrides for a misrouted workspace path
Defensive patterns

Strategy: retry

Validate before calling

// Verify config loads before invoking the tool:
// via RPC: config.get (any read) — if the config is broken this fails the same way
// in-process: config_rpc::load_config_with_timeout().await.is_ok()

Try / catch

match tool_exec("learning_save_profile", args).await {
    Err(e) if e.to_string().starts_with("learning_save_profile:") && !e.to_string().contains("failed") => {
        // config-load failure: fix config.toml first, then retry — no partial writes happened
        Err(e)
    }
    other => other,
}

Prevention

When it happens

Trigger: Hand-edited config.toml with syntax errors or invalid typed fields; config load blocked behind a contended lock until the timeout fired; workspace/config directory missing or unreadable; env override pointing at a bad path.

Common situations: User edits config.toml and leaves a typo, then asks the agent to save their profile; slow/locked filesystem (network home dir) blowing the load timeout; fresh machine without an initialized workspace.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16). Data as JSON: /api/errors/6585fbc6f7f7e841. Report an issue: GitHub.