unicity-aos/aos-ce · warning
Rejected invalid tool name
Error message
Rejected invalid tool name: {tool_name} What it means
The router validates tool names before constructing the forward topic tool.v1.execute.{tool_name}. A name that is empty or contains characters outside [alphanumeric, '-', '_', ':'] is rejected to prevent topic injection (e.g., dots creating nested topics). The warning is logged and an error result is published back to the caller with the call_id.
Solutions
- Sanitize the tool name on the caller side to allow only [A-Za-z0-9_-:], replacing dots with ':' or '-'.
- Reject or map dotted names to the router's convention before calling execute.
- Ensure empty tool names never reach the router (validate JSON-RPC params).
- If a legitimate name needs new characters, extend the allowlist in the router deliberately.
Example fix
// before
call_tool("foo.bar.baz", args) // dot rejected
// after
call_tool("foo:bar:baz", args) // ':' is allowed by the router Defensive patterns
Strategy: validation
Validate before calling
function isValidToolName(name) {
return typeof name === 'string' && name.length > 0 &&
/^[A-Za-z0-9_:-]+$/.test(name);
} Type guard
fn is_safe_tool_name(name: &str) -> bool {
!name.is_empty()
&& name.chars().all(|c| c.is_alphanumeric() || matches!(c, '-' | '_' | ':'))
} Try / catch
if (!isValidToolName(toolName)) {
console.warn('Rejected invalid tool name:', toolName);
return publishError(callId, 'Invalid tool name: ' + toolName);
} Prevention
- Never build tool names from raw user input or file paths
- Replace dots with ':' before calling execute
- Validate JSON-RPC params so empty names are caught client-side
When it happens
Trigger: handle_execute_request receives a tool_call whose name is empty, contains a dot, slash, space, or any non-allowlisted character — e.g., tool_name = "foo.bar.baz", "../exec", "my tool", or "".
Common situations: Clients building tool names from user input or file paths; LLM-generated tool calls with dotted names; namespace conventions using '.' from other ecosystems; empty names from defaulted/misbuilt JSON-RPC calls.
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
- canonical document exceeds bound
- Unicity AOS health service must bind to 127.0.0.1
- must not be empty
- must be an absolute path
- product manifest path must be a regular file
AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13).
Data as JSON: /api/errors/4ba851b8b6ddfc30.
Report an issue: GitHub.
Appendix: source
Thrown at capsules/capsule-router/src/lib.rs:44
#[astrid::interceptor("handle_execute_request")]
pub fn handle_execute_request(&self, req: IpcPayload) -> Result<(), SysError> {
let (call_id, tool_name, arguments) = match req {
IpcPayload::ToolExecuteRequest {
call_id,
tool_name,
arguments,
} => (call_id, tool_name, arguments),
_ => return Ok(()),
};
// Validate tool name: must be non-empty, alphanumeric with hyphens/underscores/colons.
// Reject dots to prevent topic injection (e.g., "foo.bar.baz" becoming nested topics).
if tool_name.is_empty()
|| tool_name
.chars()
.any(|c| !c.is_alphanumeric() && c != '-' && c != '_' && c != ':')
{
log::warn(format!("Rejected invalid tool name: {tool_name}"));
return Self::publish_error_result(&call_id, format!("Invalid tool name: {tool_name}"));
}
let forward_topic = format!("tool.v1.execute.{tool_name}");
log::info(format!(
"Routing tool request: {tool_name} -> {forward_topic}"
));
let forward_payload = IpcPayload::ToolExecuteRequest {
call_id: call_id.clone(),
tool_name: tool_name.clone(),
arguments,
};
if let Err(e) = ipc::publish_json(&forward_topic, &forward_payload) {
log::error(format!(
"Failed to forward tool request for {tool_name}: {e}"View on GitHub (pinned to f6f22024fb)