{"record":{"id":"31c3c7e19a444259","repo":"vercel/ai","slug":"open-responses-extension-extension-id-must-prov-31c3c7","errorCode":null,"errorMessage":"Open Responses extension ${extension.id} must provide itemTypes and decodeItem together.","messagePattern":"Open Responses extension (.+?) must provide itemTypes and decodeItem together\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/open-responses/src/open-responses-extension.ts","lineNumber":215,"sourceCode":"      });\n      registerUnique({\n        map: registry.byProviderToolId,\n        key: extension.id,\n        extension: toolExtension,\n        field: 'provider-tool id',\n      });\n      registerUnique({\n        map: registry.byToolType,\n        key: toolExtension.toolType,\n        extension: toolExtension,\n        field: 'toolType',\n      });\n    }\n\n    const hasItemTypes = extension.itemTypes != null;\n    const hasItemDecoder = extension.decodeItem != null;\n    if (hasItemTypes !== hasItemDecoder) {\n      throw new Error(\n        `Open Responses extension ${extension.id} must provide itemTypes and decodeItem together.`,\n      );\n    }\n\n    if (extension.encodeInputItem != null && !hasItemDecoder) {\n      throw new Error(\n        `Open Responses extension ${extension.id} cannot provide encodeInputItem without itemTypes and decodeItem.`,\n      );\n    }\n\n    if (hasItemTypes && hasItemDecoder) {\n      const itemExtension = extension as OpenResponsesItemExtension;\n      if (itemExtension.itemTypes.length === 0) {\n        throw new Error(\n          `Open Responses extension ${extension.id} must register at least one item type.`,\n        );\n      }\n      for (const itemType of itemExtension.itemTypes) {","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/open-responses/src/open-responses-extension.ts#L197-L233","documentation":"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.","triggerScenarios":"Registering an extension that sets itemTypes but not decodeItem, or decodeItem but not itemTypes, in the extensions array of the Open Responses registry.","commonSituations":"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.","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."],"exampleFix":"// before\n{ id: 'acme.ticket', itemTypes: ['ticket'] } // decodeItem missing\n// after\n{ id: 'acme.ticket', itemTypes: ['ticket'], decodeItem: (item) => ({...}) }","handlingStrategy":"validation","validationCode":"extensions.forEach(e => {\n  const x = e as any;\n  if ((x.itemTypes != null) !== (x.decodeItem != null)) {\n    throw new Error(`${x.id}: itemTypes and decodeItem must be provided together`);\n  }\n});","typeGuard":"function isCompleteItemExtension(e: object): boolean {\n  const x = e as any;\n  return (x.itemTypes != null) === (x.decodeItem != null);\n}","tryCatchPattern":"try {\n  const registry = createOpenResponsesExtensionRegistry(extensions);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('must provide itemTypes and decodeItem together')) {\n    // complete the item extension definition\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["open-responses","extension","item-decoding","validation"],"backgroundTag":"invalid-extension-configuration","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}