unicity-aos/aos-ce · error
Subscribe ` ` priority must be an integer.
Error message
Subscribe `{key}` priority must be an integer. What it means
capsule-forge validates that a [subscribe] entry's `priority` is an integer (via TOML as_integer). If `priority` is present but is a string, float, or boolean, the type cannot back the u32 dispatcher, so validation emits this error with guidance to use an integer 0..4294967295.
Solutions
- Change `priority` in the [subscribe] row to an unquoted integer between 0 and 4294967295.
- Remove quotes around numeric values if the manifest was generated from another format.
- Re-run `capsule-forge validate` to verify.
Example fix
// before ([subscribe])
"tool.v1.request.describe" = { wit = ..., handler = "tool_describe", priority = "10" }
// after
"tool.v1.request.describe" = { wit = ..., handler = "tool_describe", priority = 10 } Defensive patterns
Strategy: type-guard
Validate before calling
// Validate TOML priority type before validating the manifest
if let Some(p) = row.get("priority") {
assert!(p.is_integer(), "priority must be an integer");
} Type guard
fn priority_is_integer(v: &toml::Value) -> bool { v.is_integer() } Prevention
- Never quote numeric fields in the manifest.
- Serialize from YAML/JSON generators with numeric types preserved (not strings).
- Use a JSON/TOML schema validator in CI to enforce integer types.
When it happens
Trigger: validate_manifest -> check_tool_bus sees a [subscribe] key with a `priority` field whose TOML value is not an integer (e.g. `priority = "10"` or `priority = 1.5`).
Common situations: Quoting the priority by accident, using a float for readability, or generating the manifest from YAML/JSON where numbers were serialized as strings.
Related errors
- Subscribe ` ` has priority outside the u32 range.
- Capability ` ` must be a list.
- Capability ` ` must be a boolean.
- Subscribe ` ` has no `handler`.
- Mandatory publish key
AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13).
Data as JSON: /api/errors/af9551fa497f67b6.
Report an issue: GitHub.
Appendix: source
Thrown at capsules/capsule-forge/src/checks.rs:247
.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.",
));
}
}
}
let Some(tool) = key.strip_prefix("tool.v1.execute.") else {
continue;
};
// The `*.result` publish key would also strip; skip non-tool shapes.
if tool.contains('*') || tool.contains('.') {
continue;
}
saw_execute_tool = true;
let has_handler = sub_table
.and_then(|t| t.get(key))
.and_then(|v| v.get("handler"))View on GitHub (pinned to f6f22024fb)