{"record":{"id":"e9f8d7fcab80596f","repo":"vercel/ai","slug":"tool-choice-type-exhaustivecheck-e9f8d7","errorCode":null,"errorMessage":"tool choice type: ${_exhaustiveCheck}","messagePattern":"tool choice type: (.+?)","errorType":"exception","errorClass":"UnsupportedFunctionalityError","httpStatus":null,"severity":"error","filePath":"packages/openai/src/responses/openai-responses-prepare-tools.ts","lineNumber":541,"sourceCode":"          resolvedToolName === 'code_interpreter' ||\n          resolvedToolName === 'file_search' ||\n          resolvedToolName === 'image_generation' ||\n          resolvedToolName === 'web_search_preview' ||\n          resolvedToolName === 'web_search' ||\n          resolvedToolName === 'mcp' ||\n          resolvedToolName === 'apply_patch' ||\n          resolvedToolName === 'computer' ||\n          resolvedToolName === 'programmatic_tool_calling'\n            ? { type: resolvedToolName }\n            : resolvedCustomProviderToolNames.has(resolvedToolName)\n              ? { type: 'custom', name: resolvedToolName }\n              : { type: 'function', name: resolvedToolName },\n        toolWarnings,\n      };\n    }\n    default: {\n      const _exhaustiveCheck: never = type;\n      throw new UnsupportedFunctionalityError({\n        functionality: `tool choice type: ${_exhaustiveCheck}`,\n      });\n    }\n  }\n}\n\nfunction allowedToolKey(entry: OpenAIResponsesAllowedTool): string {\n  switch (entry.type) {\n    case 'mcp':\n      return `mcp:${entry.server_label}`;\n    case 'function':\n    case 'custom':\n      return `${entry.type}:${entry.name}`;\n    default:\n      return entry.type;\n  }\n}\n","sourceCodeStart":523,"sourceCodeEnd":559,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/openai/src/responses/openai-responses-prepare-tools.ts#L523-L559","documentation":"The toolChoice mapping switch in prepareResponsesTools is exhaustive over the known tool-choice types. When an unknown/unmapped tool choice type reaches the default branch, TypeScript's never check captures it and the SDK throws UnsupportedFunctionalityError naming the unrecognized type, guarding against silently sending invalid tool_choice values to OpenAI.","triggerScenarios":"Passing a toolChoice object whose 'type' is not one of 'auto' | 'none' | 'required' | 'tool' to an openai.responses(...) model, e.g. a mistyped type string or a tool-choice variant from a different provider/spec version.","commonSituations":"Typo like { type: 'auto ' } or { type: 'any' }; constructing toolChoice dynamically from user/config input without validation; provider spec drift where a newer type has not yet been mapped in the installed SDK version.","solutions":["Use one of the supported types: auto, none, required, or tool","Validate/normalize toolChoice before passing it to the model","Upgrade the AI SDK if you are using a newer tool-choice type added by OpenAI","Cast only if you are certain the value is valid for the current API version"],"exampleFix":"// before\ntoolChoice: { type: 'any', toolName: 'getWeather' }\n// after\ntoolChoice: { type: 'tool', toolName: 'getWeather' }","handlingStrategy":"validation","validationCode":"const VALID = new Set(['auto', 'none', 'required', 'tool']);\nif (toolChoice && !VALID.has(toolChoice.type)) {\n  throw new Error(`Invalid toolChoice type: ${toolChoice.type}`);\n}","typeGuard":"function isValidToolChoice(tc: { type: string }): tc is { type: 'auto' | 'none' | 'required' } | { type: 'tool'; toolName: string } {\n  return tc.type === 'auto' || tc.type === 'none' || tc.type === 'required' ||\n    (tc.type === 'tool' && 'toolName' in tc);\n}","tryCatchPattern":"try {\n  await generateText({ model: openai.responses('gpt-4.1'), toolChoice, ... });\n} catch (e) {\n  if (UnsupportedFunctionalityError.isInstance(e) && e.message.includes('tool choice type')) {\n    // fall back to toolChoice: 'auto' or surface a config error\n  } else throw e;\n}","preventionTips":["Rely on the SDK's TypeScript types for toolChoice instead of hand-built objects","Never construct toolChoice from unvalidated user/config input without a whitelist check","Keep the SDK up to date when OpenAI adds new tool-choice types"],"tags":["openai","tool-choice","responses-api","unsupported-functionality","typescript"],"backgroundTag":"unsupported-tool-choice-type","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}