unicity-aos/aos-ce · warning · Finding
Topic ` ` has more than 8 segments — likely a mistake.
Error message
Topic `{key}` has more than 8 segments — likely a mistake. What it means
check_topic_shapes validates every declared topic key in the manifest. Topics with more than 8 dot-separated segments trigger this warning because deeply nested topic trees usually indicate a naming mistake (e.g. embedding parameters into topic segments). The manifest still validates unless errors are also present, but the topic shape is flagged as suspicious.
Solutions
- Flatten the topic to 8 or fewer segments; move variable data (IDs, params) into the message payload, not the topic name.
- Review the naming scheme against the documented topic taxonomy in forge_guide.
- If topics are built in code, check for accidental repeated prefix concatenation.
Example fix
// before: stuffing a request id into the topic
let topic = format!("tool.v1.execute.echo.request.{req_id}.payload.result");
// after: keep the topic stable, send the id in the payload
let topic = "tool.v1.execute.echo.result";
let payload = serde_json::json!({ "request_id": req_id }); Defensive patterns
Strategy: validation
Validate before calling
# fail CI on over-deep topics
for t in $(tomlq -r '(.publish // {}) + (.subscribe // {}) | keys[]' capsule.toml); do
segs=$(echo "$t" | awk -F. '{print NF}'); [ "$segs" -gt 8 ] && echo "topic too deep: $t" && exit 1
done Type guard
fn topic_depth_ok(topic: &str) -> bool { topic.split('.').count() <= 8 } Prevention
- Put variable data in the payload, never in topic segments
- Keep topic names under the documented 8-segment limit
- Review programmatic topic construction for prefix duplication
When it happens
Trigger: validate_manifest -> check_topic_shapes processes a topic key where key.split('.').count() > 8, e.g. `tool.v1.execute.a.b.c.d.e.f.result`.
Common situations: Encoding per-request IDs or user data into topic names instead of payload fields; over-hierarchical naming conventions; concatenating topic prefixes repeatedly when building topics programmatically.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- [publish] is empty or missing — the capsule cannot publish…
- [subscribe] is empty or missing — the capsule cannot…
- 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/1d974bc4f34d2f1f.
Report an issue: GitHub.
Appendix: source
Thrown at capsules/capsule-forge/src/checks.rs:304
out.push(Finding::err(
"Subscribe `tool.v1.request.describe` is missing — tools won't be discoverable.",
"Add `\"tool.v1.request.describe\" = { wit = ..., handler = \"tool_describe\" }` to [subscribe].",
));
}
}
}
/// Flag malformed topic keys: empty segments, or absurd depth (>8 segments).
fn check_topic_shapes(pub_keys: &[String], sub_keys: &[String], out: &mut Vec<Finding>) {
for key in pub_keys.iter().chain(sub_keys) {
if has_empty_segments(key) {
out.push(Finding::err(
format!("Topic `{key}` has empty segments (leading/trailing/consecutive dots)."),
"Remove the stray dots; every segment between dots must be non-empty.",
));
}
if key.split('.').count() > 8 {
out.push(Finding::warn(
format!("Topic `{key}` has more than 8 segments — likely a mistake."),
"Flatten the topic; deep topic trees usually indicate a naming error.",
));
}
}
if out.iter().all(|f| f.level != "error") {
out.push(Finding::info(
"No blocking manifest errors found.",
"Build with `aos capsule build`, then install with `aos capsule install`.",
));
}
}
#[cfg(test)]
mod tests {
use super::validate_manifest;
#[test]View on GitHub (pinned to f6f22024fb)