vercel/ai · error · UnsupportedFunctionalityError
'tool choice type: ${type}' functionality not supported.
Error message
'tool choice type: ${type}' functionality not supported. What it means
prepareResponsesTools switches on the toolChoice type (auto/none/required/tool). The default branch is an exhaustiveness guard that throws UnsupportedFunctionalityError for any tool-choice type the xAI Responses adapter does not implement — typically reached when the SDK type system is bypassed with a cast or a newer tool-choice type exists that xAI has not mapped.
Source
Thrown at packages/xai/src/responses/xai-responses-prepare-tools.ts:208
if (selectedTool.type === 'provider') {
// xAI API does not support forcing specific server-side tools via toolChoice
// Only function tools can be forced with {"type": "function", "function": {"name": "..."}}
toolWarnings.push({
type: 'unsupported',
feature: `toolChoice for server-side tool "${selectedTool.name}"`,
});
return { tools: xaiTools, toolChoice: undefined, toolWarnings };
}
return {
tools: xaiTools,
toolChoice: { type: 'function', name: selectedTool.name },
toolWarnings,
};
}
default: {
const _exhaustiveCheck: never = type;
throw new UnsupportedFunctionalityError({
functionality: `tool choice type: ${_exhaustiveCheck}`,
});
}
}
}
View on GitHub (pinned to 69428b1f8b)
Solutions
- Use only auto | none | required | { type: 'tool', toolName } for xAI responses models
- Replace legacy values like 'any' with 'required'
- Upgrade @ai-sdk/xai to the latest version so new tool-choice types are mapped
Example fix
// before
toolChoice: { type: 'any' } as any
// after
toolChoice: { type: 'required' } Defensive patterns
Strategy: validation
Validate before calling
const allowed = ['auto','none','required','tool'];
if (toolChoice && !allowed.includes(toolChoice.type)) {
throw new Error(`toolChoice type ${toolChoice.type} not supported by xai`);
} Type guard
function isXaiToolChoice(tc: unknown): boolean {
const t = (tc as any)?.type;
return tc == null || ['auto','none','required','tool'].includes(t);
} Try / catch
try {
await generateText({ model, prompt, toolChoice: tc as any });
} catch (e) {
if ((e as any).name === 'AI_UnsupportedFunctionalityError' && (e as Error).message.includes('tool choice type')) {
// fall back to toolChoice: 'auto'
}
} Prevention
- Only use documented toolChoice values for xAI
- Map provider-specific values (like legacy 'any') to 'required' in an adapter layer
- Avoid `as any` casts around toolChoice
When it happens
Trigger: Passing toolChoice: { type: <unrecognized> } (e.g. a custom/extended value or an old spec value like 'any'/'message') with a cast to the responses-model toolChoice, causing the never check to fail at runtime.
Common situations: Migrating code from other providers where toolChoice values differ (e.g. { type: 'any' } from older SDK versions); hand-constructed provider calls; SDK version skew between spec types and provider package.
Related errors
- 'tool choice type: ${_exhaustiveCheck}' functionality not su
- 'tool choice type: ${type}' functionality not supported.
- AI_UnsupportedFunctionalityError
- AI_UnsupportedFunctionalityError
- tool choice type: ${_exhaustiveCheck}
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/38c8db5a348de7b0.
Report an issue: GitHub.