mastra-ai/mastra · error

Expected ${gatewayPrefix}/ in model router ID ${routerId}

Error message

Expected ${gatewayPrefix}/ in model router ID ${routerId}

What it means

parseModelRouterId parses a router id like "gateway/provider/model". When an optional gatewayPrefix argument is given, the id must start with that prefix followed by '/'. If it doesn't, the function throws immediately rather than mis-parsing segments. This guards against resolving a model under the wrong gateway.

Source

Thrown at packages/core/src/llm/model/gateway-resolver.ts:10

export type ResolvedModelConfig = {
  url: string | false;
  headers: Record<string, string>;
  resolvedModelId: string;
  fullModelId: string;
};

export function parseModelRouterId(routerId: string, gatewayPrefix?: string): { providerId: string; modelId: string } {
  if (gatewayPrefix && !routerId.startsWith(`${gatewayPrefix}/`)) {
    throw new Error(`Expected ${gatewayPrefix}/ in model router ID ${routerId}`);
  }

  const idParts = routerId.split('/');

  // Azure OpenAI uses 2-part format (azure-openai/deployment), others use 3-part (gateway/provider/model)
  if (gatewayPrefix === 'azure-openai') {
    const modelId = idParts.slice(1).join('/');
    if (!modelId) {
      throw new Error(`Expected format azure-openai/deployment-name, but got ${routerId}`);
    }
    return {
      providerId: 'azure-openai',
      modelId, // Deployment name
    };
  }

  // Provider-equals-gateway: a gateway whose provider id is the same as its
  // gateway id (e.g. amazon-bedrock) uses a 2-part router id (gateway/model),

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Pass an id that starts with the expected prefix, e.g. `${gatewayPrefix}/provider/model`.
  2. If the prefix is uncertain, call parseModelRouterId without gatewayPrefix and validate the first segment yourself.
  3. Verify the stored model id's gateway matches the resolver's expected gatewayPrefix before parsing.

Example fix

// before
parseModelRouterId("openai/gpt-4o", "openai-compatible");
// after
parseModelRouterId("openai-compatible/openai/gpt-4o", "openai-compatible");
Defensive patterns

Strategy: validation

Validate before calling

function assertRouterId(routerId, gatewayPrefix) {
  if (gatewayPrefix && !routerId.startsWith(`${gatewayPrefix}/`)) {
    throw new Error(`Router id must start with "${gatewayPrefix}/", got: ${routerId}`);
  }
}
assertRouterId(routerId, 'openai-compatible');
parseModelRouterId(routerId, 'openai-compatible');

Type guard

const hasGatewayPrefix = (id, prefix) => id.startsWith(`${prefix}/`);

Try / catch

try {
  const { providerId, modelId } = parseModelRouterId(routerId, gatewayPrefix);
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Expected ')) {
    console.error(`Router id "${routerId}" does not match gateway "${gatewayPrefix}"`);
  } else throw e;
}

Prevention

When it happens

Trigger: parseModelRouterId("openai/gpt-4o", "openai-compatible") (wrong prefix), or passing a bare model id like "gpt-4o" (no prefix at all) when a gatewayPrefix is expected.

Common situations: Mixing ids from different gateways (storing an azure id but resolving with an openai-compatible prefix); ids stored before a gateway migration; stripping the prefix accidentally when reading from DB or env.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/b4b498785a74dbdb. Report an issue: GitHub.