unicity-aos/aos-ce · warning · Finding
[subscribe] is empty or missing — the capsule cannot…
Error message
[subscribe] is empty or missing — the capsule cannot receive any event.
What it means
collect_topics also gathers keys from [subscribe] and warns when it is empty or missing. Subscription is fail-closed: without declared subscribe topics the capsule receives no events at all. Forge expects tool capsules to subscribe to one `tool.v1.execute.<tool>` topic per tool plus `tool.v1.request.describe`.
Solutions
- Add a [subscribe] section containing `tool.v1.execute.<tool>` for each tool the capsule implements plus `tool.v1.request.describe`.
- Check topics weren't accidentally declared under [publish]; move them to [subscribe].
- If the capsule is intentionally publish-only, accept the warning as documenting that no events are received.
Example fix
# before
[publish]
"tool.v1.execute.*.result" = {}
# after
[publish]
"tool.v1.execute.*.result" = {}
[subscribe]
"tool.v1.execute.echo" = {}
"tool.v1.request.describe" = {} Defensive patterns
Strategy: validation
Validate before calling
# ensure [subscribe] exists with required keys before shipping tomlq '.subscribe | keys' capsule.toml | grep -q 'tool.v1.execute' || echo "missing subscribe topics"
Prevention
- Declare one tool.v1.execute.<tool> per implemented tool plus tool.v1.request.describe
- Don't mix publish/subscribe sections when copying templates
- Run forge validate in CI on every manifest
When it happens
Trigger: validate_manifest -> collect_topics finds table_keys(root, "subscribe") empty — no [subscribe] section in the manifest, or it has zero topic keys.
Common situations: Fresh manifest skeleton without wiring yet; author renamed tools and removed subscriptions but never re-added them; copied a publish-only template; typo putting topics under [publish] instead of [subscribe].
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- [publish] is empty or missing — the capsule cannot publish…
- Topic ` ` has more than 8 segments — likely a mistake.
- embedded capsule source is not canonical
- Subscribe ` ` has priority outside the u32 range.
- Subscribe ` ` priority must be an integer.
AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13).
Data as JSON: /api/errors/93a4f698798134d1.
Report an issue: GitHub.
Appendix: source
Thrown at capsules/capsule-forge/src/checks.rs:204
"Remove `scope`; shared/operator-only env scope is not honoured from the manifest.",
));
}
}
}
/// Collect the `[publish]` and `[subscribe]` topic keys, warning if a table is
/// empty (fail-closed: the capsule then can't publish/subscribe at all).
fn collect_topics(root: &Toml, out: &mut Vec<Finding>) -> (Vec<String>, Vec<String>) {
let pub_keys = table_keys(root, "publish");
let sub_keys = table_keys(root, "subscribe");
if pub_keys.is_empty() {
out.push(Finding::warn(
"[publish] is empty or missing — the capsule cannot publish any event.",
"Add the tool-bus publish keys `tool.v1.execute.*.result` and `tool.v1.response.describe.*`.",
));
}
if sub_keys.is_empty() {
out.push(Finding::warn(
"[subscribe] is empty or missing — the capsule cannot receive any event.",
"Add one `tool.v1.execute.<tool>` per tool plus `tool.v1.request.describe`.",
));
}
(pub_keys, sub_keys)
}
fn table_keys(root: &Toml, table: &str) -> Vec<String> {
root.get(table)
.and_then(Toml::as_table)
.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>) {View on GitHub (pinned to f6f22024fb)