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

  1. Sanitize the tool name on the caller side to allow only [A-Za-z0-9_-:], replacing dots with ':' or '-'.
  2. Reject or map dotted names to the router's convention before calling execute.
  3. Ensure empty tool names never reach the router (validate JSON-RPC params).
  4. 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

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


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)