vllm-project/vllm · error · Error

tool_choice function `{name}` was not found in the available

Error message

tool_choice function `{name}` was not found in the available tools

What it means

Request validation error (`request.rs:517`): `tool_choice` pins a specific function `name`, but no tool with that name exists in the request's `tools` array. The offending name is carried in the error. Maps to a 4xx at the API boundary (`error.rs:97`).

Source

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

    #[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 {
        match self {
            Self::PromptTooLong { .. }
            | Self::DuplicateToolName { .. }
            | Self::ToolChoiceRequiresTools

View on GitHub (pinned to c794754062)

Solutions

  1. Verify the exact spelling/case of the function name against the tools array you are sending.
  2. Assert client-side that the pinned name exists in the tools list before issuing the request.
  3. Regenerate the tool names from a single source of truth (shared constants/registry) instead of string literals.

Example fix

// before
choice.function.name = "get_wether"; // typo

// after
choice.function.name = WEATHER_TOOL_NAME; // shared constant "get_weather"
Defensive patterns

Strategy: validation

Validate before calling

if let Some(ToolChoice::Function { name }) = &request.tool_choice {
    if !request.tools.iter().any(|t| &t.function.name == name) {
        return Err(format!("tool_choice function `{name}` not in tools"));
    }
}

Type guard

fn pinned_tool_exists(choice: Option<&ToolChoice>, tools: &[Tool]) -> bool {
    match choice {
        Some(ToolChoice::Function { name }) => tools.iter().any(|t| &t.function.name == name),
        _ => true,
    }
}

Try / catch

match result {
    Err(vllm_chat::Error::ToolChoiceFunctionNotFound { name }) => {
        respond_bad_request(format!("unknown tool `{name}` in tool_choice"))
    }
    other => other?,
}

Prevention

When it happens

Trigger: `{"tool_choice": {"type": "function", "function": {"name": "get_weather"}}, "tools": [ ...no get_weather... ]}`; usually a typo or a stale name after a tool was renamed/removed.

Common situations: Tool registry drift between client and server; renamed functions during refactors; case mismatches (`GetWeather` vs `get_weather`).

Related errors


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