{"record":{"id":"41933fdb8237b160","repo":"unicity-aos/aos-ce","slug":"aos-mcp-caller-unavailable-for-host-hook-response-error","errorCode":null,"errorMessage":"aos-mcp: caller unavailable for host-hook response: {error}","messagePattern":"aos-mcp: caller unavailable for host-hook response: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"capsules/capsule-mcp/src/host_hooks.rs","lineNumber":140,"sourceCode":"        Err(error) => {\n            reject(\"unknown\", \"unknown\", \"malformed_response\");\n            log::warn(format!(\n                \"aos-mcp: malformed host-hook bridge response: {error}\"\n            ));\n            return Ok(());\n        }\n    };\n    let event = response.event.as_deref().unwrap_or(\"unknown\");\n    if let Err(reason) = validate_response_shape(&response) {\n        reject(&response.host, event, reason);\n        return Ok(());\n    }\n\n    let caller = match runtime::caller() {\n        Ok(caller) => caller,\n        Err(error) => {\n            reject(&response.host, event, \"caller_unavailable\");\n            log::warn(format!(\n                \"aos-mcp: caller unavailable for host-hook response: {error}\"\n            ));\n            return Ok(());\n        }\n    };\n    if caller.principal.as_deref() != Some(response.principal_id.as_str()) {\n        reject(&response.host, event, \"principal_mismatch\");\n        return Ok(());\n    }\n\n    let token_key = token_key(&response.host, &response.session_id);\n    let Some(token) = kv::get_bytes_opt(&token_key)? else {\n        reject(&response.host, event, \"unknown_session_route\");\n        return Ok(());\n    };\n    let Ok(token) = std::str::from_utf8(&token) else {\n        reject(&response.host, event, \"invalid_stored_route\");\n        return Ok(());","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/unicity-aos/aos-ce/blob/f6f22024fb1e8d122f28a1b4a9f75aee448ae839/capsules/capsule-mcp/src/host_hooks.rs#L122-L158","documentation":"In relay_response, after parsing the host-hook response the capsule queries runtime::caller() to authenticate the responding principal. If the caller is unavailable, it rejects as `caller_unavailable` using the response's host and event, logs a warning, and returns Ok(()) without relaying.","triggerScenarios":"runtime::caller() errors while relaying a host-hook response — typically because the response was injected outside a host-initiated call or the runtime did not attach caller identity.","commonSituations":"Test harnesses posting responses directly, runtime versions lacking caller metadata on the response path, or host bridge misconfiguration dropping the security context.","solutions":["Deliver the response through the host bridge so runtime caller identity is present.","Upgrade/configure the runtime to propagate caller info on the response path.","Inspect the logged error detail to identify why the runtime could not resolve the caller."],"exampleFix":"// before (harness)\npost_response(capsule, payload)\n// after\nhost_bridge.deliver_response(capsule, payload) // runtime attaches caller identity","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match runtime::caller() {\n    Ok(caller) => verify_and_relay(caller, &response),\n    Err(e) => { reject(&response.host, event, \"caller_unavailable\"); log::warn!(\"caller unavailable: {e}\"); }\n}","preventionTips":["Deliver responses only through the host bridge so caller identity is attached.","Avoid test harnesses that post responses directly to the capsule entry point.","Track caller_unavailable rejections per host to catch misconfigured bridges early."],"tags":["runtime","authentication","host-hooks","mcp"],"backgroundTag":"authentication-required","analyzedSha":"f6f22024fb1e8d122f28a1b4a9f75aee448ae839","analyzedAt":"2026-09-13T03:04:44.565Z","contentChangedAt":"2026-09-13T03:04:44.565Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}