{"record":{"id":"f8bb71c184f32d2d","repo":"unicity-aos/aos-ce","slug":"aos-mcp-caller-unavailable-for-expected-host-hook-error","errorCode":null,"errorMessage":"aos-mcp: caller unavailable for {expected_host} hook: {error}","messagePattern":"aos-mcp: caller unavailable for (.+?) hook: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"capsules/capsule-mcp/src/host_hooks.rs","lineNumber":84,"sourceCode":"        Ok(request) => request,\n        Err(error) => {\n            reject(expected_host, \"unknown\", \"malformed_payload\");\n            log::warn(format!(\n                \"aos-mcp: malformed {expected_host} hook ingress: {error}\"\n            ));\n            return Ok(());\n        }\n    };\n    if let Err(reason) = validate_request(expected_host, &request) {\n        reject(expected_host, &request.event, reason);\n        return Ok(());\n    }\n\n    let caller = match runtime::caller() {\n        Ok(caller) => caller,\n        Err(error) => {\n            reject(expected_host, &request.event, \"caller_unavailable\");\n            log::warn(format!(\n                \"aos-mcp: caller unavailable for {expected_host} hook: {error}\"\n            ));\n            return Ok(());\n        }\n    };\n    if caller.principal.as_deref() != Some(request.principal_id.as_str()) {\n        reject(expected_host, &request.event, \"principal_mismatch\");\n        return Ok(());\n    }\n\n    let token_key = token_key(expected_host, &request.session_id);\n    if !authenticate_token(&token_key, &request)? {\n        reject(expected_host, &request.event, \"token_mismatch\");\n        return Ok(());\n    }\n\n    ipc::publish_json(\n        &format!(\"oracle.v1.hook.validated.{expected_host}\"),","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/unicity-aos/aos-ce/blob/f6f22024fb1e8d122f28a1b4a9f75aee448ae839/capsules/capsule-mcp/src/host_hooks.rs#L66-L102","documentation":"After parsing a host hook request, `handle` asks the runtime for the caller identity. If runtime::caller() fails, the hook is rejected as `caller_unavailable`, a warning is logged, and processing stops with Ok(()). The capsule cannot authenticate the hook without a caller, so it refuses rather than guess.","triggerScenarios":"runtime::caller() returns Err while handling a host hook — e.g. the hook was invoked outside a proper host-initiated call context or the runtime lacks caller metadata.","commonSituations":"Invoking the hook entry point directly from tooling instead of through the host, running on a runtime version that does not populate caller info, or a misconfigured host binding.","solutions":["Invoke the hook through the host bridge so the runtime can supply a caller identity.","Check the runtime/binding version supports caller metadata for hook ingress.","Read the logged error for the underlying cause (e.g. missing context) and fix the invocation environment."],"exampleFix":"// before (tooling)\ndirect_call(capsule, \"hook_ingress\", payload)\n// after\nvia_host_bridge(capsule, host, payload) // host supplies caller identity","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match runtime::caller() {\n    Ok(caller) => proceed(caller),\n    Err(e) => { reject(host, event, \"caller_unavailable\"); log::warn!(\"caller unavailable: {e}\"); }\n}","preventionTips":["Always invoke hooks via the host bridge, never direct entry-point calls from tooling.","Pin runtime and bridge versions that propagate caller metadata.","Alert on caller_unavailable rejections — they usually indicate an out-of-band invocation."],"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"}