unicity-aos/aos-ce · warning
aos-mcp: could not retire
Error message
aos-mcp: could not retire {response.host} hook route: {error} What it means
In capsule-mcp's host hook relay, after relaying a response whose shape indicates the session's hook route is finished, the code deletes the route's KV entry (kv::delete(&token_key)). If that delete fails, the stale route is left registered and this warning is logged; the response itself was still delivered successfully. This is a cleanup-failure warning, not a relay failure.
Solutions
- Check the KV backend health and the error text in the log; retry the operation once the store is available.
- Verify no concurrent consumer deletes the same token key first; make retirement idempotent.
- If the route is genuinely dead, manually remove the stale KV key for that host.
- Ignore if the route is short-lived; the warning is non-fatal and the session response was delivered.
Example fix
// before
if retires_session_route(&response)
&& let Err(error) = kv::delete(&token_key)
{
log::warn(format!("aos-mcp: could not retire {} hook route: {error}", response.host));
}
// after
if retires_session_route(&response)
&& let Err(error) = kv::delete(&token_key)
{
log::warn(format!("aos-mcp: could not retire {} hook route: {error}", response.host));
kv::delete(&token_key).ok(); // bounded retry after backoff
} Defensive patterns
Strategy: fallback
Validate before calling
// before relaying, ensure the KV token key exists and store is reachable let present = kv::get(&token_key).is_ok();
Type guard
fn route_deletable(key: &str) -> bool { kv::get(key).is_ok() } Try / catch
match kv::delete(&token_key) {
Ok(_) => {},
Err(e) => log::warn("route retire failed, retrying later: {e}"),
} Prevention
- Monitor KV backend health before session teardown
- Make route retirement idempotent
- Alert on repeated retire warnings per host
When it happens
Trigger: kv::delete(&token_key) returns Err during relay_response when retires_session_route(&response) is true — i.e., the KV store rejected or failed the delete of the hook-route token for response.host (KV backend unavailable, key already gone via a different code path, storage error).
Common situations: KV store restart or transient storage errors during session teardown; concurrent sessions deleting the same route; host misconfiguration causing token_key collisions or stale keys.
Related errors
- aos-mcp: could not audit rejected hook message
- ingress pending read error for source_id
- grant pending read error for capsule_id
AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13).
Data as JSON: /api/errors/c791f26b45400c20.
Report an issue: GitHub.
Appendix: source
Thrown at capsules/capsule-mcp/src/host_hooks.rs:173
};
let Ok(token) = std::str::from_utf8(&token) else {
reject(&response.host, event, "invalid_stored_route");
return Ok(());
};
if derive_route_id(&response.host, &response.session_id, token) != response.route_id {
reject(&response.host, event, "route_mismatch");
return Ok(());
}
ipc::publish_json(
&format!("astrid.v1.response.{}", response.delivery_id),
&response,
)?;
if retires_session_route(&response)
&& let Err(error) = kv::delete(&token_key)
{
log::warn(format!(
"aos-mcp: could not retire {} hook route: {error}",
response.host
));
}
Ok(())
}
fn authenticate_token(key: &str, request: &HostHookRequest) -> Result<bool, SysError> {
match kv::get_bytes_opt(key)? {
Some(expected) => Ok(tokens_match(request.token.as_bytes(), &expected)),
None if can_register(&request.event) => {
if kv::cas(key, None, request.token.as_bytes())? {
Ok(true)
} else {
Ok(kv::get_bytes_opt(key)?
.as_deref()
.is_some_and(|expected| tokens_match(request.token.as_bytes(), expected)))
}View on GitHub (pinned to f6f22024fb)