unicity-aos/aos-ce · warning
capability check failed for
Error message
capability check failed for {uuid}: {e}, denying What it means
capsule-prompt-builder checks, per source_id, whether the source has the 'allow_prompt_injection' capability via capabilities::check. If the check itself errors (as opposed to returning false), the result is denied (fail-closed), cached as false, and this warning is logged by fire_before_prompt_build during assemble.
Solutions
- Read the {e} detail and fix the capability backend availability or registration for that uuid.
- Register the source capsule/uuid and grant 'allow_prompt_injection' explicitly if it should be allowed.
- Clear the cached false entry (cache lives per assemble run) after fixing the backend and retry.
- Confirm fail-closed is intended; if the source doesn't need injection, the warning can be ignored.
Example fix
// before
capabilities::check(uuid, "allow_prompt_injection")
.inspect_err(|e| {
runtime_log::warn(format!("capability check failed for {uuid}: {e}, denying"));
})
.unwrap_or(false)
// after
// register uuid in the capability store, then:
capabilities::check(uuid, "allow_prompt_injection")
.inspect_err(|e| {
runtime_log::warn(format!("capability check failed for {uuid}: {e}, denying"));
})
.unwrap_or(false) // now returns Ok(true) for granted sources Defensive patterns
Strategy: validation
Validate before calling
// check capability registration before assemble
const registered = await capabilities.exists(uuid);
if (!registered) throw new Error('source not registered: ' + uuid); Try / catch
capabilities::check(uuid, "allow_prompt_injection")
.inspect_err(|e| runtime_log::warn("capability check failed for {uuid}: {e}, denying"))
.unwrap_or(false) Prevention
- Register sources and grant capabilities before assembly
- Fail-closed is intended: treat warnings as config drift signals
- Clear capability caches after fixing the backend
When it happens
Trigger: capabilities::check(uuid, "allow_prompt_injection") returns Err while building the per-uuid cache in fire_before_prompt_build — capability service unavailable, unknown uuid, or backend error resolving the source's capabilities.
Common situations: Capability store/registry outage; source uuid not yet registered; stale source_id from a removed capsule; permission configuration not yet propagated.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13).
Data as JSON: /api/errors/0657bc74cd22521e.
Report an issue: GitHub.
Appendix: source
Thrown at capsules/capsule-prompt-builder/src/lib.rs:435
// sub drops here, releasing the kernel-side subscription.
runtime_log::info(format!(
"Collected {} hook responses for request {}",
sourced_responses.len(),
request.request_id
));
// Cache capability results per-UUID to avoid redundant host function calls.
// Multiple hook responses can come from the same capsule.
let mut cache = std::collections::HashMap::<String, bool>::new();
filter_by_permission(sourced_responses, |source_id| {
let Some(uuid) = source_id else {
return false;
};
*cache.entry(uuid.to_owned()).or_insert_with(|| {
capabilities::check(uuid, "allow_prompt_injection")
.inspect_err(|e| {
runtime_log::warn(format!("capability check failed for {uuid}: {e}, denying"));
})
.unwrap_or(false)
})
})
}
/// Parse a single IPC message and extract hook responses with source capsule IDs.
fn parse_hook_message(msg: &ipc::Message) -> Option<Vec<SourcedHookResponse>> {
let payload: serde_json::Value = match serde_json::from_str(&msg.payload) {
Ok(v) => v,
Err(e) => {
runtime_log::warn(format!("failed to deserialize hook response payload: {e}"));
return None;
}
};
let source_id = if msg.source_id.is_empty() {
NoneView on GitHub (pinned to f6f22024fb)