{"record":{"id":"b2e9ace87e7e338d","repo":"tinyhumansai/openhuman","slug":"secret-request-timed-out-after-s","errorCode":null,"errorMessage":"secret request {} timed out after {}s","messagePattern":"secret request (.+?) timed out after (.+?)s","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/openhuman/mcp/registry/setup.rs","lineNumber":159,"sourceCode":"    }\n    tracing::debug!(\"[mcp-setup] fulfilled ref={}\", r.as_str());\n    true\n}\n\n/// Block on a freshly-minted request with the global timeout. On timeout\n/// the entry is removed and `Err(_)` is returned.\npub async fn await_fulfillment(r: &SecretRef, rx: oneshot::Receiver<()>) -> anyhow::Result<()> {\n    match timeout(REQUEST_TIMEOUT, rx).await {\n        Ok(Ok(())) => Ok(()),\n        Ok(Err(_)) => {\n            // Sender dropped — usually means GC purged the entry. Surface\n            // as a timeout-style error to keep the caller simple.\n            let _ = forget(r).await;\n            anyhow::bail!(\"secret request {} cancelled before user submit\", r.as_str())\n        }\n        Err(_) => {\n            let _ = forget(r).await;\n            anyhow::bail!(\n                \"secret request {} timed out after {}s\",\n                r.as_str(),\n                REQUEST_TIMEOUT.as_secs()\n            )\n        }\n    }\n}\n\n/// Resolve a `{KEY: SecretRef}` map into a `Vec<(KEY, VALUE)>`. Returns\n/// `Err(_)` if any ref is unknown or not yet fulfilled — callers should\n/// retry rather than partially-apply.\n///\n/// Touches the `last_touched` on every hit so iterative `test_connection`\n/// calls reset the idle TTL.\npub async fn resolve_refs(\n    refs: &HashMap<String, SecretRef>,\n) -> anyhow::Result<Vec<(String, String)>> {\n    let mut guard = map().lock().await;","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/mcp/registry/setup.rs#L141-L177","documentation":"Same wait as the cancelled variant, but the full REQUEST_TIMEOUT (300 s / 5 minutes) elapsed without the user submitting the secret. The entry is explicitly forgotten via forget(r) on this path, so retrying the same SecretRef cannot succeed — a new request must be minted. This is a user-absence condition, not a system fault.","triggerScenarios":"await_fulfillment waits the full 300 s while the user never submits: the prompt was left open and abandoned, an unattended/scripted install expected pre-provisioned env values, or the frontend failed to render the secret dialog at all.","commonSituations":"AFK user; headless run where an interactive secret prompt can never be answered; UI bug hiding the prompt; CI invoking install flows that require credentials.","solutions":["Re-run the install in an interactive session and submit the secret within the 5-minute window.","For unattended flows, pre-provision the values (e.g. via the mcp_client_env path used at consume time) instead of relying on the interactive request.","If the prompt never appeared, check the frontend dialog wiring before retrying — the timeout will just repeat."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"Branch on the message: `timed out after 300s` → mint a new request and re-prompt (the old SecretRef was forgotten via forget()); distinguish from `cancelled before user submit`, which indicates GC/supersession rather than user absence.","preventionTips":["Submit secrets within the 5-minute REQUEST_TIMEOUT window.","Pre-provision env values for unattended installs instead of the interactive path.","Surface prompt age/deadline in the UI so users see the cutoff."],"tags":["mcp","secrets","install","timeout"],"backgroundTag":"operation-timed-out","analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}