unicity-aos/aos-ce · error
Subscribe ` ` sets `priority` without a `handler`.
Error message
Subscribe `{key}` sets `priority` without a `handler`. What it means
`check_tool_bus` validates bus subscription entries: `priority` only makes sense for subscriptions that carry a `handler` binding. If a subscribe entry sets `priority` but has no non-empty `handler` string (e.g. an ACL-only subscription), this error is emitted for the offending key. Priority without a handler is meaningless scheduling metadata the runtime cannot use.
Solutions
- Add a real `handler` binding to the `{key}` subscription so `priority` is meaningful.
- Remove the `priority` key from the ACL-only subscription if no handler is intended.
- Split ACL-only subscriptions from handler subscriptions in the manifest to keep them structurally distinct.
Example fix
// before [tool_bus.subscribe.events] priority = 5 // after [tool_bus.subscribe.events] handler = "my_handler" priority = 5
Defensive patterns
Strategy: validation
Validate before calling
// Rust
if entry.get("priority").is_some()
&& !entry.get("handler").and_then(|h| h.as_str()).map_or(false, |h| !h.is_empty())
{
return Err(format!("subscribe `{key}`: priority requires handler"));
} Prevention
- Only add `priority` to subscriptions that also declare a non-empty `handler`.
- Keep ACL-only subscriptions and handler subscriptions as separate entries.
- Review subscription tables whenever copying entries between manifests.
When it happens
Trigger: A subscription entry under the subscribe table with `priority = 5` but no `handler` key, or `handler = ""` (empty string fails `has_handler`).
Common situations: Copying a handler subscription template and stripping the handler but leaving priority, configuring ACL-only subscriptions that previously shared a table with handler entries, or hand-merging two subscription configs.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- `capabilities` must be a TOML table.
- Capability ` ` must be a list.
- Capability ` ` must be a boolean.
- [package].name is missing or empty.
- [package].version is missing.
AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13).
Data as JSON: /api/errors/a923e799f183d34b.
Report an issue: GitHub.
Appendix: source
Thrown at capsules/capsule-forge/src/checks.rs:233
.map(|t| t.keys().cloned().collect())
.unwrap_or_default()
}
/// Check the mandatory tool-bus wiring: each `tool.v1.execute.<x>` subscribe has
/// a handler, the two mandatory publish keys exist, and the describe request is
/// subscribed.
fn check_tool_bus(sub_keys: &[String], pub_keys: &[String], root: &Toml, out: &mut Vec<Finding>) {
let sub_table = root.get("subscribe").and_then(Toml::as_table);
let mut saw_execute_tool = false;
for key in sub_keys {
if let Some(entry) = sub_table.and_then(|table| table.get(key)) {
let has_handler = entry
.get("handler")
.and_then(Toml::as_str)
.is_some_and(|handler| !handler.is_empty());
if entry.get("priority").is_some() && !has_handler {
out.push(Finding::err(
format!("Subscribe `{key}` sets `priority` without a `handler`."),
"Add a real handler binding or remove priority from the ACL-only subscription.",
));
}
if let Some(priority) = entry.get("priority") {
if let Some(priority) = priority.as_integer() {
if !(0..=u32::MAX.into()).contains(&priority) {
out.push(Finding::err(
format!("Subscribe `{key}` has priority outside the u32 range."),
"Use an integer from 0 through 4294967295; lower values run first.",
));
}
} else {
out.push(Finding::err(
format!("Subscribe `{key}` priority must be an integer."),
"Use an integer from 0 through 4294967295; lower values run first.",
));
}View on GitHub (pinned to f6f22024fb)