vercel/ai · error
Open Responses extension ${extension.id} must provide itemTy
Error message
Open Responses extension ${extension.id} must provide itemTypes and decodeItem together. What it means
An Open Responses item extension must pair itemTypes (the item type strings it can decode) with decodeItem (the decoder). Providing one without the other would break round-tripping of items, so the registry throws at construction time.
Source
Thrown at packages/open-responses/src/open-responses-extension.ts:215
});
registerUnique({
map: registry.byProviderToolId,
key: extension.id,
extension: toolExtension,
field: 'provider-tool id',
});
registerUnique({
map: registry.byToolType,
key: toolExtension.toolType,
extension: toolExtension,
field: 'toolType',
});
}
const hasItemTypes = extension.itemTypes != null;
const hasItemDecoder = extension.decodeItem != null;
if (hasItemTypes !== hasItemDecoder) {
throw new Error(
`Open Responses extension ${extension.id} must provide itemTypes and decodeItem together.`,
);
}
if (extension.encodeInputItem != null && !hasItemDecoder) {
throw new Error(
`Open Responses extension ${extension.id} cannot provide encodeInputItem without itemTypes and decodeItem.`,
);
}
if (hasItemTypes && hasItemDecoder) {
const itemExtension = extension as OpenResponsesItemExtension;
if (itemExtension.itemTypes.length === 0) {
throw new Error(
`Open Responses extension ${extension.id} must register at least one item type.`,
);
}
for (const itemType of itemExtension.itemTypes) {View on GitHub (pinned to 69428b1f8b)
Solutions
- Provide itemTypes and decodeItem together as a matched pair.
- Remove both if the extension should not handle items.
- Annotate the extension as OpenResponsesItemExtension so the type system requires both.
Example fix
// before
{ id: 'acme.ticket', itemTypes: ['ticket'] } // decodeItem missing
// after
{ id: 'acme.ticket', itemTypes: ['ticket'], decodeItem: (item) => ({...}) } Defensive patterns
Strategy: validation
Validate before calling
extensions.forEach(e => {
const x = e as any;
if ((x.itemTypes != null) !== (x.decodeItem != null)) {
throw new Error(`${x.id}: itemTypes and decodeItem must be provided together`);
}
}); Type guard
function isCompleteItemExtension(e: object): boolean {
const x = e as any;
return (x.itemTypes != null) === (x.decodeItem != null);
} Try / catch
try {
const registry = createOpenResponsesExtensionRegistry(extensions);
} catch (e) {
if (e instanceof Error && e.message.includes('must provide itemTypes and decodeItem together')) {
// complete the item extension definition
}
throw e;
} Prevention
- Build item extensions via a factory requiring (itemTypes, decodeItem) together.
- Type extensions as OpenResponsesItemExtension for compile-time completeness.
- Test registry construction for every custom extension in CI.
- Keep itemTypes entries and decoder branches in a single source of truth.
When it happens
Trigger: Registering an extension that sets itemTypes but not decodeItem, or decodeItem but not itemTypes, in the extensions array of the Open Responses registry.
Common situations: Adding a decoder for a custom item and forgetting to list its type strings; declaring itemTypes while deferring/omitting the decoder implementation; partial object spreads in configuration.
Related errors
- Open Responses extension ID ${extension.id} must use <implem
- Open Responses extension ${extension.id} must provide toolTy
- Open Responses extension ${extension.id} cannot provide enco
- Open Responses extension ${extension.id} cannot provide enco
- maxEmbeddingsPerCall must be greater than 0
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/31c3c7e19a444259.
Report an issue: GitHub.