unicity-aos/aos-ce · warning

aos-mcp: caller unavailable for host-hook response

Error message

aos-mcp: caller unavailable for host-hook response: {error}

What it means

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.

Solutions

  1. Deliver the response through the host bridge so runtime caller identity is present.
  2. Upgrade/configure the runtime to propagate caller info on the response path.
  3. Inspect the logged error detail to identify why the runtime could not resolve the caller.

Example fix

// before (harness)
post_response(capsule, payload)
// after
host_bridge.deliver_response(capsule, payload) // runtime attaches caller identity
Defensive patterns

Strategy: try-catch

Try / catch

match runtime::caller() {
    Ok(caller) => verify_and_relay(caller, &response),
    Err(e) => { reject(&response.host, event, "caller_unavailable"); log::warn!("caller unavailable: {e}"); }
}

Prevention

When it happens

Trigger: 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.

Common situations: Test harnesses posting responses directly, runtime versions lacking caller metadata on the response path, or host bridge misconfiguration dropping the security context.

Related errors


AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13). Data as JSON: /api/errors/41933fdb8237b160. Report an issue: GitHub.

Appendix: source

Thrown at capsules/capsule-mcp/src/host_hooks.rs:140

        Err(error) => {
            reject("unknown", "unknown", "malformed_response");
            log::warn(format!(
                "aos-mcp: malformed host-hook bridge response: {error}"
            ));
            return Ok(());
        }
    };
    let event = response.event.as_deref().unwrap_or("unknown");
    if let Err(reason) = validate_response_shape(&response) {
        reject(&response.host, event, reason);
        return Ok(());
    }

    let caller = match runtime::caller() {
        Ok(caller) => caller,
        Err(error) => {
            reject(&response.host, event, "caller_unavailable");
            log::warn(format!(
                "aos-mcp: caller unavailable for host-hook response: {error}"
            ));
            return Ok(());
        }
    };
    if caller.principal.as_deref() != Some(response.principal_id.as_str()) {
        reject(&response.host, event, "principal_mismatch");
        return Ok(());
    }

    let token_key = token_key(&response.host, &response.session_id);
    let Some(token) = kv::get_bytes_opt(&token_key)? else {
        reject(&response.host, event, "unknown_session_route");
        return Ok(());
    };
    let Ok(token) = std::str::from_utf8(&token) else {
        reject(&response.host, event, "invalid_stored_route");
        return Ok(());

View on GitHub (pinned to f6f22024fb)