{"record":{"id":"19ec1edee47a3dd7","repo":"zed-industries/zed","slug":"openai-chat-completions-does-not-support-custom-to","errorCode":null,"errorMessage":"OpenAI Chat Completions does not support custom tools; use Responses API instead","messagePattern":"OpenAI Chat Completions does not support custom tools; use Responses API instead","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/open_ai/src/completion.rs","lineNumber":65,"sourceCode":"    MaxCompletionTokens,\n    MaxTokens,\n}\n\npub fn into_open_ai(\n    request: LanguageModelRequest,\n    model_id: &str,\n    supports_parallel_tool_calls: bool,\n    supports_prompt_cache_key: bool,\n    max_output_tokens: Option<u64>,\n    max_tokens_parameter: ChatCompletionMaxTokensParameter,\n    reasoning_effort: Option<ReasoningEffort>,\n    interleaved_reasoning: bool,\n) -> Result<crate::Request> {\n    if request\n        .tools\n        .iter()\n        .any(|tool| matches!(tool.input, LanguageModelRequestToolInput::Custom { .. }))\n    {\n        return Err(anyhow!(\n            \"OpenAI Chat Completions does not support custom tools; use Responses API instead\"\n        ));\n    }\n\n    let stream = !model_id.starts_with(\"o1-\");\n    let service_tier = service_tier_for(request.speed);\n\n    let mut messages = Vec::new();\n    let mut current_reasoning: Option<String> = None;\n    for message in request.messages {\n        let reasoning_details = interleaved_reasoning\n            .then(|| message.reasoning_details.clone())\n            .flatten();\n        for content in message.content {\n            match content {\n                MessageContent::Thinking { text, .. } if interleaved_reasoning => {\n                    current_reasoning.get_or_insert_default().push_str(&text);","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/zed-industries/zed/blob/5a9b9558db01a6b906cec2fb70a797affdc58cdd/crates/open_ai/src/completion.rs#L47-L83","documentation":"Capability guard in into_open_ai: the request includes a tool with LanguageModelRequestToolInput::Custom, which the Chat Completions API cannot express, so conversion refuses up front rather than sending a request OpenAI would reject.","triggerScenarios":"Thrown at crates/open_ai/src/completion.rs:65 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Use OpenAI's Responses API path for custom tools","Disable custom tools for Chat Completions models"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"5a9b9558db01a6b906cec2fb70a797affdc58cdd","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}