vllm-project/vllm · error · Error

duplicate tool name `{name}`

Error message

duplicate tool name `{name}`

What it means

Request validation error raised at `request.rs:497` when the `tools` array contains two tool definitions with the same function name. Tool names are the dispatch key for `tool_choice` and for matching `tool_call_id`s, so duplicates are rejected up front. Classified as a user request error (`error.rs:95`).

Source

Thrown at rust/src/chat/src/error.rs:74

    HarmonyParserOverrideUnsupported {
        kind: &'static str,
        selection: String,
    },
    #[error("harmony output parsing failed")]
    HarmonyOutputParsing {
        #[source]
        error: BoxedError,
    },
    #[error(
        "this model's maximum context length is {max_model_len} tokens, \
         but the prompt contains {prompt_len} input tokens"
    )]
    PromptTooLong { max_model_len: u32, prompt_len: u32 },
    #[error("chat request stream `{request_id}` closed before terminal output")]
    StreamClosedBeforeTerminalOutput { request_id: String },
    #[error("tool call stream state is inconsistent: {message}")]
    ToolCallStreamInvariant { message: String },
    #[error("duplicate tool name `{name}`")]
    DuplicateToolName { name: String },
    #[error("tool_choice requires at least one available tool")]
    ToolChoiceRequiresTools,
    #[error("tool_choice function `{name}` was not found in the available tools")]
    ToolChoiceFunctionNotFound { name: String },
    #[error("failed to build structural tag: {message}")]
    StructuralTag { message: String },
    #[error(transparent)]
    Text(#[from] vllm_text::Error),
    #[error(transparent)]
    Tokenizer(#[from] vllm_tokenizer::TokenizerError),
}

pub type Result<T> = std::result::Result<T, Error>;

impl Error {
    /// Whether this error represents invalid user request parameters.
    pub fn is_request_validation_error(&self) -> bool {

View on GitHub (pinned to c794754062)

Solutions

  1. Dedupe the tools array by function name before sending (keep last or error in client code).
  2. Namespace tool names per module (`fs_read_file` vs `db_read_file`) when merging registries.
  3. Add a unit test / lint that asserts uniqueness of tool names in your tool-registry builder.

Example fix

// before
let tools = [fs_tools(), db_tools()]; // both contain "read"

// after
let tools = dedup_by_name([fs_tools(), db_tools()])?;
Defensive patterns

Strategy: validation

Validate before calling

let mut seen = HashSet::new();
for tool in &tools {
    if !seen.insert(tool.function.name.as_str()) {
        return Err(format!("duplicate tool name: {}", tool.function.name));
    }
}

Type guard

fn has_unique_tool_names(tools: &[Tool]) -> bool {
    let mut seen = std::collections::HashSet::new();
    tools.iter().all(|t| seen.insert(t.function.name.as_str()))
}

Try / catch

match result {
    Err(vllm_chat::Error::DuplicateToolName { name }) => {
        respond_bad_request(format!("duplicate tool name `{name}`"))
    }
    other => other?,
}

Prevention

When it happens

Trigger: POSTing a chat completion with `tools: [{function:{name:"search"}}, {function:{name:"search"}}]`; common when programmatically merging tool lists from multiple modules without dedup.

Common situations: Combining tool registries from several plugins that each define `get_time` or `search`; renaming one tool but forgetting call sites that construct the list; copy-pasted tool JSON.

Related errors


AI-assisted analysis of vllm-project/vllm@c794754062 (2026-08-14). Data as JSON: /api/errors/37aa38e1947814c6. Report an issue: GitHub.