{"record":{"id":"ed5a590578c72f15","repo":"tinyhumansai/openhuman","slug":"learning-enrich-profile-e-ed5a59","errorCode":null,"errorMessage":"learning_enrich_profile: {e:#}","messagePattern":"learning_enrich_profile: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/openhuman/agent/learning/tools.rs","lineNumber":603,"sourceCode":"    fn external_effect(&self) -> bool {\n        true\n    }\n\n    async fn execute(&self, args: serde_json::Value) -> anyhow::Result<ToolResult> {\n        log::debug!(\"[tool][learning] enrich_profile invoked\");\n        let preset = args\n            .get(\"profile_url\")\n            .and_then(serde_json::Value::as_str)\n            .map(str::to_string);\n        let config = config_rpc::load_config_with_timeout()\n            .await\n            .map_err(|e| anyhow::anyhow!(\"learning_enrich_profile: {e}\"))?;\n        let result =\n            crate::openhuman::agent::learning::linkedin_enrichment::run_linkedin_enrichment(\n                &config, preset,\n            )\n            .await\n            .map_err(|e| anyhow::anyhow!(\"learning_enrich_profile: {e:#}\"))?;\n        Ok(ToolResult::success(serde_json::to_string(&json!({\n            \"profile_url\": result.profile_url,\n            \"profile_data\": result.profile_data,\n            \"stages\": result.stages,\n            \"log\": result.log,\n        }))?))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::openhuman::tools::traits::ToolScope;\n\n    #[test]\n    fn names_and_levels() {\n        assert_eq!(LearningListFacetsTool.name(), \"learning_list_facets\");\n        assert_eq!(","sourceCodeStart":585,"sourceCodeEnd":621,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/src/openhuman/agent/learning/tools.rs#L585-L621","documentation":"Thrown by learning_enrich_profile when run_linkedin_enrichment() fails — a multi-stage external pipeline: it needs a signed-in integration client ('no integration client — user not signed in'), goes through Composio/Apify (LinkedIn scrape, 'Apify run failed' / empty items) and Gmail evidence fetch, then writes PROFILE.md and persists the profile into the memory store. Any stage failure bubbles up here with the full {e:#} chain naming the broken stage.","triggerScenarios":"User not signed in / LinkedIn integration not connected; missing or invalid Composio/Apify credentials; Apify run failing or returning zero items for a private/hidden profile; network outage mid-scrape; memory client unavailable at persist time; PROFILE.md write failure.","commonSituations":"First enrichment attempt before connecting the LinkedIn integration; expired third-party tokens; scraping profiles that require login walls; flaky upstream Apify jobs.","solutions":["Read the {e:#} chain first — it names the exact stage ('no integration client', 'Apify run failed', 'GMAIL_FETCH_EMAILS failed', store/write errors)","Sign in / reconnect the LinkedIn integration in Connections, then retry","Verify Composio/Apify credentials and network reachability","For a profile that yields empty items, pass an explicit profile_url and retry, or fall back to learning_save_profile with pasted markdown"],"exampleFix":"// before\ntool: learning_enrich_profile {} // -> learning_enrich_profile: no integration client — user not signed in\n// after: connect LinkedIn in Connections UI, then\ntool: learning_enrich_profile {\"profile_url\":\"https://www.linkedin.com/in/<handle>\"}","handlingStrategy":"validation","validationCode":"// Preconditions from the pipeline's own failure modes:\n// 1) integration client must exist (user signed in) — check Connections status for LinkedIn\n// 2) Composio/Apify credentials configured\n// 3) workspace writable (learning_save_profile with empty-ish markdown succeeds)\n// Only then invoke learning_enrich_profile.","typeGuard":null,"tryCatchPattern":"match tool_exec(\"learning_enrich_profile\", args).await {\n    Err(e) => {\n        let msg = e.to_string();\n        if msg.contains(\"no integration client\") || msg.contains(\"not signed in\") {\n            return Err(e); // auth — retrying won't help until the user connects\n        }\n        if msg.contains(\"Apify\") || msg.contains(\"GMAIL\") || msg.contains(\"timeout\") {\n            tokio::time::sleep(Duration::from_secs(5)).await;\n            return tool_exec(\"learning_enrich_profile\", args).await; // transient upstream\n        }\n        Err(e)\n    }\n    ok => ok,\n}","preventionTips":["Connect the LinkedIn integration (sign in) before the first enrichment run","Pass an explicit profile_url rather than relying on discovery","On repeated Apify 'empty items', fall back to pasting the profile via learning_save_profile","The error chain names the failing stage — always read it before retrying blindly"],"tags":["rust","integration","linkedin","scraping","network","learning"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}