{"record":{"id":"aa5eef6d87c767c4","repo":"vercel/ai","slug":"deepseek-strict-tool-calls-require-a-beta-base-url","errorCode":null,"errorMessage":"DeepSeek strict tool calls require a beta base URL ending in `/beta`.","messagePattern":"DeepSeek strict tool calls require a beta base URL ending in `/beta`\\.","errorType":"exception","errorClass":"UnsupportedFunctionalityError","httpStatus":null,"severity":"error","filePath":"packages/deepseek/src/chat/deepseek-prepare-tools.ts","lineNumber":37,"sourceCode":"}): {\n  tools: undefined | Array<DeepSeekFunctionTool>;\n  toolChoice: DeepSeekToolChoice;\n  toolWarnings: SharedV4Warning[];\n} {\n  // when the tools array is empty, change it to undefined to prevent errors:\n  tools = tools?.length ? tools : undefined;\n\n  const toolWarnings: SharedV4Warning[] = [];\n\n  if (tools == null) {\n    return { tools: undefined, toolChoice: undefined, toolWarnings };\n  }\n\n  const functionTools = tools.filter(tool => tool.type === 'function');\n  const hasStrictTool = functionTools.some(tool => tool.strict === true);\n\n  if (hasStrictTool && supportsStrictToolCalls === false) {\n    throw new UnsupportedFunctionalityError({\n      functionality: 'DeepSeek strict tool calls',\n      message:\n        'DeepSeek strict tool calls require a beta base URL ending in `/beta`.',\n    });\n  }\n\n  if (\n    hasStrictTool &&\n    supportsStrictToolCalls === true &&\n    functionTools.some(tool => tool.strict !== true)\n  ) {\n    throw new UnsupportedFunctionalityError({\n      functionality: 'mixed DeepSeek strict and non-strict tool calls',\n      message:\n        'DeepSeek strict mode requires every function tool in the request to set `strict: true`.',\n    });\n  }\n","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/deepseek/src/chat/deepseek-prepare-tools.ts#L19-L55","documentation":"DeepSeek strict tool calls are a beta-only feature. prepareTools throws UnsupportedFunctionalityError when any function tool has strict: true but the provider was constructed without a /beta base URL (supportsStrictToolCalls === false).","triggerScenarios":"Passing a tool with strict: true (e.g. tool({ ..., strict: true }) or zod-as-function with strict) to generateText/streamText with a DeepSeek model created with a non-beta baseURL.","commonSituations":"Copying strict-mode examples while using the production endpoint; enabling strict: true globally via a helper after migrating from OpenAI where strict is GA.","solutions":["Create the DeepSeek provider with baseURL 'https://api.deepseek.com/beta'","Or remove strict: true from the tools","Or use the beta model variant factory if the provider exposes one"],"exampleFix":"// before\nconst deepseek = createDeepSeek({ apiKey });\nconst tools = { weather: tool({ inputSchema, execute, strict: true }) };\n// after\nconst deepseek = createDeepSeek({ apiKey, baseURL: 'https://api.deepseek.com/beta' });","handlingStrategy":"validation","validationCode":"const baseURL = process.env.DEEPSEEK_BASE_URL ?? 'https://api.deepseek.com';\nfunction assertBetaForStrictTools(tools) {\n  const anyStrict = Object.values(tools).some(t => t?.strict === true);\n  if (anyStrict && !baseURL.endsWith('/beta')) {\n    throw new Error('strict tool calls require a baseURL ending in /beta');\n  }\n}","typeGuard":null,"tryCatchPattern":"try { ... } catch (e) { if (UnsupportedFunctionalityError.isInstance(e) && /strict tool calls/.test(e.message)) { /* switch endpoint or drop strict */ } throw e; }","preventionTips":["Pair strict: true usage with the /beta base URL in config","Centralize provider creation so the endpoint is set in one place","Document the beta requirement next to any strict tool definitions"],"tags":["deepseek","tools","strict","beta","base-url"],"backgroundTag":"feature-requires-beta-endpoint","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}