{"record":{"id":"38ab61b8c9db679b","repo":"mastra-ai/mastra","slug":"expected-atleast-3-id-parts-gatewayprefix-provi","errorCode":null,"errorMessage":"Expected atleast 3 id parts ${gatewayPrefix}/provider/model, but only saw ${idParts.length} in ${routerId}","messagePattern":"Expected atleast 3 id parts (.+?)/provider/model, but only saw (.+?) in (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/llm/model/gateway-resolver.ts","lineNumber":44,"sourceCode":"\n  // Provider-equals-gateway: a gateway whose provider id is the same as its\n  // gateway id (e.g. amazon-bedrock) uses a 2-part router id (gateway/model),\n  // because there is no separate provider segment to namespace. Catalog ids\n  // for such gateways are always two parts (model ids contain no slashes).\n  if (gatewayPrefix && idParts.length === 2 && idParts[0] === gatewayPrefix) {\n    const modelId = idParts[1];\n    if (!modelId) {\n      throw new Error(`Expected format ${gatewayPrefix}/model, but got ${routerId}`);\n    }\n    return {\n      providerId: gatewayPrefix,\n      modelId,\n    };\n  }\n\n  // Standard 3-part format for other prefixed gateways (Netlify, etc.)\n  if (gatewayPrefix && idParts.length < 3) {\n    throw new Error(\n      `Expected atleast 3 id parts ${gatewayPrefix}/provider/model, but only saw ${idParts.length} in ${routerId}`,\n    );\n  }\n\n  const providerId = idParts.at(gatewayPrefix ? 1 : 0);\n  const modelId = idParts.slice(gatewayPrefix ? 2 : 1).join(`/`);\n\n  if (!routerId.includes(`/`) || !providerId || !modelId) {\n    throw new Error(\n      `Attempted to parse provider/model from ${routerId} but this ID doesn't appear to contain a provider`,\n    );\n  }\n\n  return {\n    providerId,\n    modelId,\n  };\n}","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/llm/model/gateway-resolver.ts#L26-L62","documentation":"parseModelRouterId splits a model router ID into providerId and modelId. When a gateway prefix is supplied (other than azure-openai or a provider-equals-gateway gateway), the ID must be a 3-part string of the form `<gatewayPrefix>/<providerId>/<modelId>`. This error is thrown when fewer than 3 slash-separated parts are found, meaning the model ID or provider segment is missing.","triggerScenarios":"Calling parseModelRouterId with a gatewayPrefix (e.g. 'netlify') and a routerId that only has 1 or 2 slash-separated parts, such as 'netlify' or 'netlify/openai' instead of 'netlify/openai/gpt-4o'.","commonSituations":"Passing a bare model ID like 'gpt-4o' or a partial gateway ID like 'netlify/openai' where a fully prefixed router ID is expected; hand-constructed model IDs; copy-pasting a provider-only model string from another library.","solutions":["Use the full 3-part format gatewayPrefix/provider/model, e.g. 'netlify/openai/gpt-4o' instead of 'netlify/openai'.","If the model ID itself contains slashes, verify you are not splitting/truncating the ID before it reaches parseModelRouterId.","If this gateway legitimately uses a 2-part gateway/model format (provider equals gateway, like amazon-bedrock), confirm the gateway resolver passes the correct gatewayPrefix so the 2-part branch at line 31 is taken instead.","Check where the routerId originates (catalog, config, user input) and validate the segment count before calling the resolver."],"exampleFix":"// before\nconst model = gateway.resolveModel('netlify/openai');\n// after\nconst model = gateway.resolveModel('netlify/openai/gpt-4o');","handlingStrategy":"validation","validationCode":"function ensureGatewayRouterId(routerId: string, gatewayPrefix?: string): void {\n  if (gatewayPrefix && !routerId.startsWith(`${gatewayPrefix}/`)) {\n    throw new Error(`Router ID must start with ${gatewayPrefix}/`);\n  }\n  const parts = routerId.split('/').filter(Boolean);\n  if (gatewayPrefix && gatewayPrefix !== 'azure-openai' && parts.length < 3) {\n    throw new Error(`Router ID must be ${gatewayPrefix}/provider/model, got: ${routerId}`);\n  }\n}","typeGuard":"function isThreePartRouterId(routerId: string, gatewayPrefix: string): boolean {\n  return routerId.startsWith(`${gatewayPrefix}/`) && routerId.split('/').filter(Boolean).length >= 3;\n}","tryCatchPattern":"try {\n  const { providerId, modelId } = parseModelRouterId(routerId, gatewayPrefix);\n} catch (e) {\n  throw new Error(`Invalid gateway router ID \"${routerId}\"; expected ${gatewayPrefix}/provider/model`, { cause: e });\n}","preventionTips":["Always construct router IDs as gatewayPrefix/provider/model template strings.","Validate ID segment count before calling resolution APIs.","Never strip slashes from model IDs that may contain them (modelId keeps its internal slashes)."],"tags":["model-router","parsing","invalid-model-id","gateway"],"backgroundTag":"invalid-model-id","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}